GCC Code Coverage Report


Directory: ./
File: sql/item_func.cc
Date: 2022-12-13 11:44:05
Exec Total Coverage
Lines: 5042 5384 93.6%
Branches: 4294 6407 67.0%

Line Branch Exec Source
1 /* Copyright (c) 2000, 2022, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /**
24 @file
25
26 @brief
27 This file defines all numerical Items
28 */
29
30 #include "sql/item_func.h"
31
32 #include <algorithm>
33 #include <atomic>
34 #include <cfloat> // DBL_DIG
35 #include <cmath> // std::log2
36 #include <cstdio>
37 #include <cstring>
38 #include <ctime>
39 #include <initializer_list>
40 #include <iosfwd>
41 #include <limits> // std::numeric_limits
42 #include <memory>
43 #include <new>
44 #include <string>
45 #include <type_traits>
46 #include <unordered_map>
47 #include <utility>
48
49 #include "integer_digits.h"
50 #include "m_string.h"
51 #include "map_helpers.h"
52 #include "mutex_lock.h" // MUTEX_LOCK
53 #include "my_bit.h" // my_count_bits
54 #include "my_bitmap.h"
55 #include "my_byteorder.h"
56 #include "my_dbug.h"
57 #include "my_double2ulonglong.h"
58 #include "my_hostname.h"
59 #include "my_loglevel.h"
60 #include "my_psi_config.h"
61 #include "my_sqlcommand.h"
62 #include "my_sys.h"
63 #include "my_systime.h"
64 #include "my_thread.h"
65 #include "my_user.h" // parse_user
66 #include "mysql/components/services/bits/mysql_cond_bits.h"
67 #include "mysql/components/services/bits/mysql_mutex_bits.h"
68 #include "mysql/components/services/bits/psi_bits.h"
69 #include "mysql/components/services/bits/psi_mutex_bits.h"
70 #include "mysql/components/services/log_builtins.h"
71 #include "mysql/components/services/log_shared.h"
72 #include "mysql/mysql_lex_string.h"
73 #include "mysql/plugin_audit.h"
74 #include "mysql/psi/mysql_cond.h"
75 #include "mysql/psi/mysql_mutex.h"
76 #include "mysql/service_mysql_password_policy.h"
77 #include "mysql/service_thd_wait.h"
78 #include "mysql/status_var.h"
79 #include "prealloced_array.h"
80 #include "sql-common/json_dom.h" // Json_wrapper
81 #include "sql/auth/auth_acls.h"
82 #include "sql/auth/auth_common.h" // check_password_strength
83 #include "sql/auth/sql_security_ctx.h"
84 #include "sql/binlog.h" // mysql_bin_log
85 #include "sql/check_stack.h"
86 #include "sql/current_thd.h" // current_thd
87 #include "sql/dd/info_schema/table_stats.h" // dd::info_schema::Table_stati...
88 #include "sql/dd/info_schema/tablespace_stats.h" // dd::info_schema::Tablesp...
89 #include "sql/dd/object_id.h"
90 #include "sql/dd/properties.h" // dd::Properties
91 #include "sql/dd/types/abstract_table.h"
92 #include "sql/dd/types/column.h"
93 #include "sql/dd/types/index.h" // Index::enum_index_type
94 #include "sql/dd_sql_view.h" // push_view_warning_or_error
95 #include "sql/dd_table_share.h" // dd_get_old_field_type
96 #include "sql/debug_sync.h" // DEBUG_SYNC
97 #include "sql/derror.h" // ER_THD
98 #include "sql/error_handler.h" // Internal_error_handler
99 #include "sql/item.h" // Item_json
100 #include "sql/item_cmpfunc.h" // get_datetime_value
101 #include "sql/item_json_func.h" // get_json_wrapper
102 #include "sql/item_strfunc.h" // Item_func_concat_ws
103 #include "sql/item_subselect.h" // Item_subselect
104 #include "sql/key.h"
105 #include "sql/log_event.h" // server_version
106 #include "sql/mdl.h"
107 #include "sql/mysqld.h" // log_10 stage_user_sleep
108 #include "sql/parse_tree_helpers.h" // PT_item_list
109 #include "sql/parse_tree_node_base.h" // Parse_context
110 #include "sql/protocol.h"
111 #include "sql/psi_memory_key.h"
112 #include "sql/resourcegroups/resource_group.h"
113 #include "sql/resourcegroups/resource_group_basic_types.h"
114 #include "sql/resourcegroups/resource_group_mgr.h"
115 #include "sql/rpl_gtid.h"
116 #include "sql/rpl_mi.h" // Master_info
117 #include "sql/rpl_msr.h" // channel_map
118 #include "sql/rpl_rli.h" // Relay_log_info
119 #include "sql/sp.h" // sp_setup_routine
120 #include "sql/sp_head.h" // sp_name
121 #include "sql/sp_pcontext.h" // sp_variable
122 #include "sql/sql_array.h" // just to keep clang happy
123 #include "sql/sql_audit.h" // audit_global_variable
124 #include "sql/sql_base.h" // Internal_error_handler_holder
125 #include "sql/sql_bitmap.h"
126 #include "sql/sql_class.h" // THD
127 #include "sql/sql_cmd.h"
128 #include "sql/sql_derived.h" // Condition_pushdown
129 #include "sql/sql_error.h"
130 #include "sql/sql_exchange.h" // sql_exchange
131 #include "sql/sql_executor.h"
132 #include "sql/sql_lex.h"
133 #include "sql/sql_list.h"
134 #include "sql/sql_load.h" // Sql_cmd_load_table
135 #include "sql/sql_optimizer.h" // JOIN
136 #include "sql/sql_parse.h" // check_stack_overrun
137 #include "sql/sql_show.h" // append_identifier
138 #include "sql/sql_time.h" // TIME_from_longlong_packed
139 #include "sql/sql_zip_dict.h"
140 #include "sql/strfunc.h" // find_type
141 #include "sql/system_variables.h"
142 #include "sql/thd_raii.h"
143 #include "sql/val_int_compare.h" // Integer_value
144 #include "sql_string.h"
145 #include "template_utils.h" // pointer_cast
146 #include "thr_mutex.h"
147
148 #ifdef WITH_WSREP
149 #include "wsrep_trans_observer.h"
150 #endif /* WITH_WSREP */
151
152 class Protocol;
153 class sp_rcontext;
154
155 using std::max;
156 using std::min;
157
158 144956 static void free_user_var(user_var_entry *entry) { entry->destroy(); }
159
160 static int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
161 const Name_string &name,
162 user_var_entry **out_entry);
163
164 20497 bool check_reserved_words(const char *name) {
165 20497 if (!my_strcasecmp(system_charset_info, name, "GLOBAL") ||
166
6/6
✓ Branch 0 taken 20437 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 20394 times.
✓ Branch 3 taken 43 times.
✓ Branch 4 taken 116 times.
✓ Branch 5 taken 20381 times.
40891 !my_strcasecmp(system_charset_info, name, "LOCAL") ||
167
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 20381 times.
20394 !my_strcasecmp(system_charset_info, name, "SESSION"))
168 116 return true;
169 20381 return false;
170 }
171
172 58 void report_conversion_error(const CHARSET_INFO *to_cs, const char *from,
173 size_t from_length, const CHARSET_INFO *from_cs) {
174 char printable_buff[32];
175
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 convert_to_printable(printable_buff, sizeof(printable_buff), from,
176 from_length, from_cs, 6);
177 58 const char *from_name = from_cs->csname;
178 58 const char *to_name = to_cs->csname;
179
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 my_error(ER_CANNOT_CONVERT_STRING, MYF(0), printable_buff, from_name,
180 to_name);
181 58 }
182
183 /**
184 Simplify the string arguments to a function, if possible.
185
186 Currently used to substitute const values with character strings
187 in the desired character set. Only used during resolving.
188
189 @param thd thread handler
190 @param c Desired character set and collation
191 @param args Pointer to argument array
192 @param nargs Number of arguments to process
193
194 @returns false if success, true if error
195 */
196 605285 bool simplify_string_args(THD *thd, const DTCollation &c, Item **args,
197 uint nargs) {
198 // Only used during resolving
199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 605285 times.
605285 assert(!thd->lex->is_exec_started());
200
201
2/2
✓ Branch 0 taken 97087 times.
✓ Branch 1 taken 508198 times.
605285 if (thd->lex->is_view_context_analysis()) return false;
202
203 uint i;
204 Item **arg;
205
2/2
✓ Branch 0 taken 508364 times.
✓ Branch 1 taken 508197 times.
1016561 for (i = 0, arg = args; i < nargs; i++, arg++) {
206 size_t dummy_offset;
207 // Only convert const values.
208
3/4
✓ Branch 0 taken 508364 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27334 times.
✓ Branch 3 taken 481030 times.
979749 if (!(*arg)->const_item()) continue;
209
3/4
✓ Branch 0 taken 481030 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 471383 times.
✓ Branch 3 taken 9647 times.
481030 if (!String::needs_conversion(1, (*arg)->collation.collation, c.collation,
210 &dummy_offset))
211 471383 continue;
212
213 9647 StringBuffer<STRING_BUFFER_USUAL_SIZE> original;
214 9647 StringBuffer<STRING_BUFFER_USUAL_SIZE> converted;
215
1/2
✓ Branch 0 taken 9647 times.
✗ Branch 1 not taken.
9647 String *ostr = (*arg)->val_str(&original);
216
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9645 times.
9647 if (ostr == nullptr) {
217
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (thd->is_error()) return true;
218
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 *arg = new (thd->mem_root) Item_null;
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (*arg == nullptr) return true;
220 2 continue;
221 }
222 uint conv_status;
223
1/2
✓ Branch 0 taken 9645 times.
✗ Branch 1 not taken.
9645 converted.copy(ostr->ptr(), ostr->length(), ostr->charset(), c.collation,
224 &conv_status);
225
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9644 times.
9645 if (conv_status != 0) {
226
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 report_conversion_error(c.collation, ostr->ptr(), ostr->length(),
227 ostr->charset());
228 1 return true;
229 }
230 // If source is a binary string, the string may have to be validated:
231
3/6
✓ Branch 0 taken 9644 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9644 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9644 times.
9644 if (c.collation != &my_charset_bin && ostr->charset() == &my_charset_bin &&
232 !converted.is_valid_string(c.collation)) {
233 report_conversion_error(c.collation, ostr->ptr(), ostr->length(),
234 ostr->charset());
235 return true;
236 }
237
238
1/2
✓ Branch 0 taken 9644 times.
✗ Branch 1 not taken.
9644 char *ptr = thd->strmake(converted.ptr(), converted.length());
239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9644 times.
9644 if (ptr == nullptr) return true;
240 Item *conv = new (thd->mem_root)
241
2/4
✓ Branch 0 taken 9644 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9644 times.
✗ Branch 3 not taken.
9644 Item_string(ptr, converted.length(), converted.charset(), c.derivation);
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9644 times.
9644 if (conv == nullptr) return true;
243
244 9644 *arg = conv;
245
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9644 times.
9644 assert(conv->fixed);
247
6/6
✓ Branch 0 taken 9644 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9644 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
9650 }
248 508197 return false;
249 }
250
251 /**
252 Evaluate an argument string and return it in the desired character set.
253 Perform character set conversion if needed.
254 Perform character set validation (from a binary string) if needed.
255
256 @param to_cs The desired character set
257 @param arg Argument to evaluate as a string value
258 @param buffer String buffer where argument is evaluated, if necessary
259
260 @returns string pointer if success, NULL if error or NULL value
261 */
262
263 694973037 String *eval_string_arg(const CHARSET_INFO *to_cs, Item *arg, String *buffer) {
264
1/2
✓ Branch 0 taken 694973150 times.
✗ Branch 1 not taken.
694973037 StringBuffer<STRING_BUFFER_USUAL_SIZE> local_string(nullptr, 0, to_cs);
265
266 size_t offset;
267 const bool convert =
268
1/2
✓ Branch 0 taken 694973133 times.
✗ Branch 1 not taken.
694973150 String::needs_conversion(0, arg->collation.collation, to_cs, &offset);
269
3/4
✓ Branch 0 taken 1760128 times.
✓ Branch 1 taken 693213005 times.
✓ Branch 2 taken 694973089 times.
✗ Branch 3 not taken.
694973133 String *res = arg->val_str(convert ? &local_string : buffer);
270
271 // Return immediately if argument is a NULL value, or there was an error
272
2/2
✓ Branch 0 taken 1687843 times.
✓ Branch 1 taken 693285246 times.
694973089 if (res == nullptr) {
273 1687843 return nullptr;
274 }
275
2/2
✓ Branch 0 taken 1759797 times.
✓ Branch 1 taken 691525449 times.
693285246 if (convert) {
276 /*
277 String must be converted from source character set. It has been built
278 in the "local_string" buffer and will be copied with conversion into the
279 caller provided buffer.
280 */
281 1759797 uint errors = 0;
282 1759797 buffer->length(0);
283
1/2
✓ Branch 0 taken 1759801 times.
✗ Branch 1 not taken.
1759802 buffer->copy(res->ptr(), res->length(), res->charset(), to_cs, &errors);
284
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1759796 times.
1759801 if (errors) {
285
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 report_conversion_error(to_cs, res->ptr(), res->length(), res->charset());
286 5 return nullptr;
287 }
288 1759796 return buffer;
289 }
290 // If source is a binary string, the string may have to be validated:
291
6/6
✓ Branch 0 taken 691280072 times.
✓ Branch 1 taken 245377 times.
✓ Branch 2 taken 739390 times.
✓ Branch 3 taken 690540682 times.
✓ Branch 4 taken 31 times.
✓ Branch 5 taken 691525418 times.
692264839 if (to_cs != &my_charset_bin && arg->collation.collation == &my_charset_bin &&
292
3/4
✓ Branch 0 taken 739390 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 739359 times.
739390 !res->is_valid_string(to_cs)) {
293
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 report_conversion_error(to_cs, res->ptr(), res->length(), res->charset());
294 31 return nullptr;
295 }
296 // Adjust target character set to the desired value
297 691525418 res->set_charset(to_cs);
298 691525377 return res;
299 694973052 }
300
301 /**
302 Evaluate a constant condition, represented by an Item tree
303
304 @param thd Thread handler
305 @param cond The constant condition to evaluate
306 @param[out] value Returned value, either true or false
307
308 @returns false if evaluation is successful, true otherwise
309 */
310
311 54817 bool eval_const_cond(THD *thd, Item *cond, bool *value) {
312 // Function may be used both during resolving and during optimization:
313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54817 times.
54817 assert(cond->may_evaluate_const(thd));
314 54817 *value = cond->val_bool();
315 54817 return thd->is_error();
316 }
317
318 /**
319 Test if the sum of arguments overflows the ulonglong range.
320 */
321 5883213 static inline bool test_if_sum_overflows_ull(ulonglong arg1, ulonglong arg2) {
322 5883213 return ULLONG_MAX - arg1 < arg2;
323 }
324
325 4618664 bool Item_func::set_arguments(mem_root_deque<Item *> *list, bool context_free) {
326 4618664 allowed_arg_cols = 1;
327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4618667 times.
4618664 if (alloc_args(*THR_MALLOC, list->size())) return true;
328 4618667 std::copy(list->begin(), list->end(), args);
329
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 4618649 times.
4618676 if (!context_free) {
330
3/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 27 times.
92 for (const Item *arg : make_array(args, arg_count)) {
331 65 add_accum_properties(arg);
332 }
333 }
334 4618676 list->clear(); // Fields are used
335 4618665 return false;
336 }
337
338 4460380 Item_func::Item_func(const POS &pos, PT_item_list *opt_list)
339 4460380 : Item_result_field(pos), allowed_arg_cols(1) {
340
2/2
✓ Branch 0 taken 90990 times.
✓ Branch 1 taken 4369404 times.
4460394 if (opt_list == nullptr) {
341 90990 args = m_embedded_arguments;
342 90990 arg_count = 0;
343 } else
344
1/2
✓ Branch 0 taken 4369396 times.
✗ Branch 1 not taken.
4369404 set_arguments(&opt_list->value, true);
345 4460386 }
346
347 1464338 Item_func::Item_func(THD *thd, const Item_func *item)
348 : Item_result_field(thd, item),
349 1464354 null_on_null(item->null_on_null),
350 1464354 allowed_arg_cols(item->allowed_arg_cols),
351 1464354 used_tables_cache(item->used_tables_cache),
352 1464338 not_null_tables_cache(item->not_null_tables_cache) {
353
2/4
✓ Branch 0 taken 1464358 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1464358 times.
1464354 if (alloc_args(thd->mem_root, item->arg_count)) return;
354
1/2
✓ Branch 0 taken 1464354 times.
✗ Branch 1 not taken.
1464358 std::copy_n(item->args, arg_count, args);
355 }
356
357 31330627 bool Item_func::itemize(Parse_context *pc, Item **res) {
358
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 31330686 times.
31330627 if (skip_itemize(res)) return false;
359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31330798 times.
31330686 if (Item_result_field::itemize(pc, res)) return true;
360 31330798 const bool no_named_params = !may_have_named_parameters();
361
2/2
✓ Branch 0 taken 72179148 times.
✓ Branch 1 taken 31330549 times.
103509697 for (size_t i = 0; i < arg_count; i++) {
362 72179148 add_accum_properties(args[i]);
363
2/2
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 72179045 times.
72179142 if (args[i]->itemize(pc, &args[i])) return true;
364
6/6
✓ Branch 0 taken 72153934 times.
✓ Branch 1 taken 25111 times.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 72153891 times.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 72179002 times.
72179045 if (no_named_params && !args[i]->item_name.is_autogenerated()) {
365
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41 times.
43 my_error(functype() == FUNC_SP ? ER_WRONG_PARAMETERS_TO_STORED_FCT
366 : ER_WRONG_PARAMETERS_TO_NATIVE_FCT,
367 43 MYF(0), func_name());
368 43 return true;
369 }
370 }
371 31330549 return false;
372 }
373
374 /*
375 Resolve references to table column for a function and its argument
376
377 SYNOPSIS:
378 fix_fields()
379 thd Thread object
380
381 DESCRIPTION
382 Call fix_fields() for all arguments to the function. The main intention
383 is to allow all Item_field() objects to setup pointers to the table fields.
384
385 Sets as a side effect the following class variables:
386 maybe_null Set if any argument may return NULL
387 used_tables_cache Set to union of the tables used by arguments
388
389 str_value.charset If this is a string function, set this to the
390 character set for the first argument.
391 If any argument is binary, this is set to binary
392
393 If for any item any of the defaults are wrong, then this can
394 be fixed in the resolve_type() function that is called after this one or
395 by writing a specialized fix_fields() for the item.
396
397 RETURN VALUES
398 false ok
399 true Got error. Stored with my_error().
400 */
401
402 40640958 bool Item_func::fix_fields(THD *thd, Item **) {
403
4/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 40640955 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
40640958 assert(fixed == 0 || basic_const_item());
404
405 Item **arg, **arg_end;
406 uchar buff[STACK_BUFF_ALLOC]; // Max argument in function
407
408 40640958 Condition_context CCT(thd->lex->current_query_block());
409
410
1/2
✓ Branch 0 taken 40641023 times.
✗ Branch 1 not taken.
40641041 used_tables_cache = get_initial_pseudo_tables();
411 40641023 not_null_tables_cache = 0;
412
413 /*
414 Use stack limit of STACK_MIN_SIZE * 2 since
415 on some platforms a recursive call to fix_fields
416 requires more than STACK_MIN_SIZE bytes (e.g. for
417 MIPS, it takes about 22kB to make one recursive
418 call to Item_func::fix_fields())
419 */
420
3/4
✓ Branch 0 taken 40641162 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 40641161 times.
40641023 if (check_stack_overrun(thd, STACK_MIN_SIZE * 2, buff))
421 1 return true; // Fatal error if flag is set!
422
2/2
✓ Branch 0 taken 39047563 times.
✓ Branch 1 taken 1593598 times.
40641161 if (arg_count) { // Print purify happy
423
2/2
✓ Branch 0 taken 93549131 times.
✓ Branch 1 taken 39042553 times.
132591684 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
424
3/4
✓ Branch 0 taken 93549070 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4949 times.
✓ Branch 3 taken 93544121 times.
93549131 if (fix_func_arg(thd, arg)) return true;
425 }
426 }
427
428
8/10
✓ Branch 0 taken 40636115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40635657 times.
✓ Branch 3 taken 458 times.
✓ Branch 4 taken 40635660 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 40635652 times.
✓ Branch 8 taken 512 times.
✓ Branch 9 taken 40635606 times.
40636151 if (resolve_type(thd) || thd->is_error()) // Some impls still not error-safe
429 512 return true;
430 40635606 fixed = true;
431 40635606 return false;
432 40641068 }
433
434 93551725 bool Item_func::fix_func_arg(THD *thd, Item **arg) {
435
6/6
✓ Branch 0 taken 50108778 times.
✓ Branch 1 taken 43442947 times.
✓ Branch 2 taken 4861 times.
✓ Branch 3 taken 50103862 times.
✓ Branch 4 taken 4861 times.
✓ Branch 5 taken 93546809 times.
93551725 if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
436 4861 return true; /* purecov: inspected */
437 93546809 Item *item = *arg;
438
439
2/2
✓ Branch 0 taken 81342406 times.
✓ Branch 1 taken 12204403 times.
93546809 if (allowed_arg_cols) {
440
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 81342306 times.
81342406 if (item->check_cols(allowed_arg_cols)) return true;
441 } else {
442 /* we have to fetch allowed_arg_cols from first argument */
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12204403 times.
12204403 assert(arg == args); // it is first argument
444 12204403 allowed_arg_cols = item->cols();
445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12204527 times.
12204527 assert(allowed_arg_cols); // Can't be 0 any more
446 }
447
448
4/4
✓ Branch 0 taken 74921169 times.
✓ Branch 1 taken 18625609 times.
✓ Branch 2 taken 15965670 times.
✓ Branch 3 taken 58955597 times.
93546833 set_nullable(is_nullable() || item->is_nullable());
449 93546830 used_tables_cache |= item->used_tables();
450
2/2
✓ Branch 0 taken 67665383 times.
✓ Branch 1 taken 25881448 times.
93546831 if (null_on_null) not_null_tables_cache |= item->not_null_tables();
451 93546810 add_accum_properties(item);
452
453 93546836 return false;
454 }
455
456 25102282 void Item_func::fix_after_pullout(Query_block *parent_query_block,
457 Query_block *removed_query_block) {
458
2/2
✓ Branch 0 taken 398916 times.
✓ Branch 1 taken 24703367 times.
25102282 if (const_item()) {
459 /*
460 Pulling out a const item changes nothing to it. Moreover, some items may
461 have decided that they're const by some other logic than the generic
462 one below, and we must preserve that decision.
463 */
464 398916 return;
465 }
466
467 Item **arg, **arg_end;
468
469 24703367 used_tables_cache = get_initial_pseudo_tables();
470 24703367 not_null_tables_cache = 0;
471
472
2/2
✓ Branch 0 taken 24695609 times.
✓ Branch 1 taken 7758 times.
24703367 if (arg_count) {
473
2/2
✓ Branch 0 taken 66437622 times.
✓ Branch 1 taken 24695567 times.
91133189 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
474 66437622 Item *const item = *arg;
475 66437622 item->fix_after_pullout(parent_query_block, removed_query_block);
476 66437620 used_tables_cache |= item->used_tables();
477
2/2
✓ Branch 0 taken 24197092 times.
✓ Branch 1 taken 42240501 times.
66437593 if (null_on_null) not_null_tables_cache |= item->not_null_tables();
478 }
479 }
480 }
481
482 /**
483 Default implementation for all functions:
484 Propagate base_item's type into all arguments.
485
486 The functions that have context-aware parameter type detection must
487 implement Item::default_data_type() and Item::resolve_type_inner().
488
489 If an SQL function or operator F embeds another SQL function or
490 operator G: F::fix_fields() runs and calls G::fix_fields() which calls
491 G::resolve_type(); assuming that G is outer-context dependent and has only
492 dynamic parameters as arguments, G misses type information and thus does a
493 no-op resolve_type(); then F::fix_fields() continues and calls
494 F::resolve_type() which sees that G::data_type() == MYSQL_TYPE_INVALID;
495 F thus calls G::propagate_type() to send it the necessary type
496 information (i.e. provide the outer context); this then assigns the type
497 to dynamic parameters of G and finishes the job of G::resolve_type() by
498 calling G::resolve_type_inner().
499 */
500 62 bool Item_func::propagate_type(THD *thd, const Type_properties &type) {
501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 assert(data_type() == MYSQL_TYPE_INVALID);
502
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 62 times.
201 for (uint i = 0; i < arg_count; i++) {
503
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 15 times.
139 if (args[i]->data_type() == MYSQL_TYPE_INVALID)
504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
124 if (args[i]->propagate_type(thd, type)) return true;
505 }
506
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 61 times.
62 if (resolve_type_inner(thd)) return true;
507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 assert(data_type() != MYSQL_TYPE_INVALID);
508
509 61 return false;
510 }
511
512 /**
513 For arguments of this Item_func ("args" array), in range
514 [start, start+step, start+2*step,...,end[ : if they're a PS
515 parameter with invalid (not known) type, give them default type "def".
516 @param thd thread handler
517 @param start range's start (included)
518 @param end range's end (excluded)
519 @param step range's step
520 @param def default type
521
522 @returns false if success, true if error
523 */
524 22599468 bool Item_func::param_type_is_default(THD *thd, uint start, uint end, uint step,
525 enum_field_types def) {
526
2/2
✓ Branch 0 taken 31781739 times.
✓ Branch 1 taken 17982862 times.
49764601 for (uint i = start; i < end; i += step) {
527
2/2
✓ Branch 0 taken 4616611 times.
✓ Branch 1 taken 27165128 times.
31781739 if (i >= arg_count) break;
528
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27165133 times.
27165128 if (args[i]->propagate_type(thd, def)) return true;
529 }
530 22599473 return false;
531 }
532
533 /**
534 For arguments of this Item_func ("args" array), in range [start,end[ :
535 sends error if they're a dynamic parameter.
536 @param start range's start (included)
537 @param end range's end (excluded)
538 @returns true if error.
539 */
540 156170 bool Item_func::param_type_is_rejected(uint start, uint end) {
541
2/2
✓ Branch 0 taken 156184 times.
✓ Branch 1 taken 24 times.
156208 for (uint i = start; i < end; i++) {
542
2/2
✓ Branch 0 taken 156143 times.
✓ Branch 1 taken 41 times.
156184 if (i >= arg_count) break;
543
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 38 times.
41 if (args[i]->data_type() == MYSQL_TYPE_INVALID) {
544 3 my_error(ER_INVALID_PARAMETER_USE, MYF(0), "?");
545 3 return true;
546 }
547 }
548 156167 return false;
549 }
550
551 /**
552 For arguments of this Item_func ("args" array), all of them: find an
553 argument that is not a dynamic parameter; if found, all dynamic parameters
554 without a valid type get the type of this; if not found, they get type "def".
555
556 @param thd thread handler
557 @param arg_count number of arguments to check
558 @param args array of arguments, size 'arg_count'
559 @param def default type
560
561 @returns false if success, true if error
562 */
563 22952160 inline bool param_type_uses_non_param_inner(THD *thd, uint arg_count,
564 Item **args, enum_field_types def) {
565 // Use first non-parameter type as base item
566 // @todo If there are multiple non-parameter items, we could use a
567 // consolidated type instead of the first one (consider CASE, COALESCE,
568 // BETWEEN).
569 22952160 uint col_cnt = args[0]->cols();
570
2/2
✓ Branch 0 taken 786 times.
✓ Branch 1 taken 22951363 times.
22952149 if (col_cnt > 1) {
571 /*
572 Row or subquery object: set parameter type recursively for the ith
573 Item in each argument row.
574 */
575
1/2
✓ Branch 0 taken 772 times.
✗ Branch 1 not taken.
786 Item **arguments = new (*THR_MALLOC) Item *[arg_count];
576
2/2
✓ Branch 0 taken 1802 times.
✓ Branch 1 taken 755 times.
2557 for (uint i = 0; i < col_cnt; i++) {
577
2/2
✓ Branch 0 taken 4214 times.
✓ Branch 1 taken 1785 times.
5999 for (uint j = 0; j < arg_count; j++) {
578
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 4197 times.
4214 if (args[j]->cols() != col_cnt) // Column count not checked yet
579 17 return false;
580
2/2
✓ Branch 0 taken 3140 times.
✓ Branch 1 taken 1057 times.
4197 if (args[j]->type() == Item::ROW_ITEM)
581 3140 arguments[j] = down_cast<Item_row *>(args[j])->element_index(i);
582
1/2
✓ Branch 0 taken 1057 times.
✗ Branch 1 not taken.
1057 else if (args[j]->type() == Item::SUBSELECT_ITEM)
583 1057 arguments[j] = (*down_cast<Item_subselect *>(args[j])
584 1057 ->unit->get_unit_column_types())[i];
585 }
586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1785 times.
1785 if (param_type_uses_non_param_inner(thd, arg_count, arguments, def))
587 return true;
588 }
589 // Resolving for row done, set data type to MYSQL_TYPE_NULL as final action.
590
2/2
✓ Branch 0 taken 1776 times.
✓ Branch 1 taken 755 times.
2531 for (uint j = 0; j < arg_count; j++)
591 1776 args[j]->set_data_type(MYSQL_TYPE_NULL);
592 755 return false;
593 }
594 22951363 Item *base_item = nullptr;
595
2/2
✓ Branch 0 taken 22952237 times.
✓ Branch 1 taken 60 times.
22952297 for (uint i = 0; i < arg_count; i++) {
596
2/2
✓ Branch 0 taken 22951304 times.
✓ Branch 1 taken 934 times.
22952237 if (args[i]->data_type() != MYSQL_TYPE_INVALID) {
597 22951304 base_item = args[i];
598 22951304 break;
599 }
600 }
601
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 22951244 times.
22951364 if (base_item == nullptr) {
602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
120 if (args[0]->propagate_type(thd, def)) return true;
603 120 base_item = args[0];
604 }
605
2/2
✓ Branch 0 taken 47292096 times.
✓ Branch 1 taken 22951412 times.
70243508 for (uint i = 0; i < arg_count; i++) {
606
2/2
✓ Branch 0 taken 47283386 times.
✓ Branch 1 taken 8742 times.
47292096 if (args[i]->data_type() != MYSQL_TYPE_INVALID) continue;
607
2/4
✓ Branch 0 taken 8758 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8758 times.
8742 if (args[i]->propagate_type(thd, Type_properties(*base_item))) return true;
608 }
609 22951412 return false;
610 }
611
612 27740596 bool Item_func::param_type_uses_non_param(THD *thd, enum_field_types def) {
613
2/2
✓ Branch 0 taken 4790187 times.
✓ Branch 1 taken 22950409 times.
27740596 if (arg_count == 0) return false;
614 22950409 return param_type_uses_non_param_inner(thd, arg_count, args, def);
615 }
616
617 45864002 bool Item_func::walk(Item_processor processor, enum_walk walk,
618 uchar *argument) {
619
8/8
✓ Branch 0 taken 14634293 times.
✓ Branch 1 taken 31231122 times.
✓ Branch 2 taken 10162010 times.
✓ Branch 3 taken 4472283 times.
✓ Branch 4 taken 41 times.
✓ Branch 5 taken 14634010 times.
✓ Branch 6 taken 41 times.
✓ Branch 7 taken 45865132 times.
45864002 if ((walk & enum_walk::PREFIX) && (this->*processor)(argument)) return true;
620
621 Item **arg, **arg_end;
622
2/2
✓ Branch 0 taken 110456968 times.
✓ Branch 1 taken 45855361 times.
156312329 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
623
2/2
✓ Branch 0 taken 9947 times.
✓ Branch 1 taken 110447197 times.
110456968 if ((*arg)->walk(processor, walk, argument)) return true;
624 }
625
6/6
✓ Branch 0 taken 31672601 times.
✓ Branch 1 taken 14183816 times.
✓ Branch 2 taken 27158313 times.
✓ Branch 3 taken 4514288 times.
✓ Branch 4 taken 975 times.
✓ Branch 5 taken 31671400 times.
45855361 return (walk & enum_walk::POSTFIX) && (this->*processor)(argument);
626 }
627
628 void Item_func::traverse_cond(Cond_traverser traverser, void *argument,
629 traverse_order order) {
630 if (arg_count) {
631 Item **arg, **arg_end;
632
633 switch (order) {
634 case (PREFIX):
635 (*traverser)(this, argument);
636 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
637 (*arg)->traverse_cond(traverser, argument, order);
638 }
639 break;
640 case (POSTFIX):
641 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
642 (*arg)->traverse_cond(traverser, argument, order);
643 }
644 (*traverser)(this, argument);
645 }
646 } else
647 (*traverser)(this, argument);
648 }
649
650 /**
651 Transform an Item_func object with a transformer callback function.
652
653 The function recursively applies the transform method to each
654 argument of the Item_func node.
655 If the call of the method for an argument item returns a new item
656 the old item is substituted for a new one.
657 After this the transformer is applied to the root node
658 of the Item_func object.
659 */
660
661 906391 Item *Item_func::transform(Item_transformer transformer, uchar *argument) {
662
2/2
✓ Branch 0 taken 136384 times.
✓ Branch 1 taken 770007 times.
906391 if (arg_count) {
663 Item **arg, **arg_end;
664
2/2
✓ Branch 0 taken 272897 times.
✓ Branch 1 taken 136384 times.
409281 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
665 272897 *arg = (*arg)->transform(transformer, argument);
666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 272897 times.
272897 if (*arg == nullptr) return nullptr; /* purecov: inspected */
667 }
668 }
669
2/2
✓ Branch 0 taken 151882 times.
✓ Branch 1 taken 754509 times.
906391 return (this->*transformer)(argument);
670 }
671
672 /**
673 Compile Item_func object with a processor and a transformer
674 callback functions.
675
676 First the function applies the analyzer to the root node of
677 the Item_func object. Then if the analyzer succeeeds (returns true)
678 the function recursively applies the compile method to each argument
679 of the Item_func node.
680 If the call of the method for an argument item returns a new item
681 the old item is substituted for a new one.
682 After this the transformer is applied to the root node
683 of the Item_func object.
684 */
685
686 9600900 Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p,
687 Item_transformer transformer, uchar *arg_t) {
688
4/4
✓ Branch 0 taken 6599805 times.
✓ Branch 1 taken 3001095 times.
✓ Branch 2 taken 55658 times.
✓ Branch 3 taken 9545324 times.
9600900 if (!(this->*analyzer)(arg_p)) return this;
689
2/2
✓ Branch 0 taken 9228018 times.
✓ Branch 1 taken 317306 times.
9545324 if (arg_count) {
690 Item **arg, **arg_end;
691
2/2
✓ Branch 0 taken 19581705 times.
✓ Branch 1 taken 9228114 times.
28809819 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
692 /*
693 The same parameter value of arg_p must be passed
694 to analyze any argument of the condition formula.
695 */
696 19581705 uchar *arg_v = *arg_p;
697
1/2
✓ Branch 0 taken 19581751 times.
✗ Branch 1 not taken.
19581705 Item *new_item = (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
698
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19581749 times.
19581751 if (new_item == nullptr) return nullptr;
699
4/6
✓ Branch 0 taken 94854 times.
✓ Branch 1 taken 19486895 times.
✓ Branch 2 taken 94854 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 94906 times.
✗ Branch 5 not taken.
19581749 if (*arg != new_item) current_thd->change_item_tree(arg, new_item);
700 }
701 }
702
2/2
✓ Branch 0 taken 6065391 times.
✓ Branch 1 taken 3480029 times.
9545420 return (this->*transformer)(arg_t);
703 }
704
705 /**
706 See comments in Item_cmp_func::split_sum_func()
707 */
708
709 401002 void Item_func::split_sum_func(THD *thd, Ref_item_array ref_item_array,
710 mem_root_deque<Item *> *fields) {
711 Item **arg, **arg_end;
712
2/2
✓ Branch 0 taken 756946 times.
✓ Branch 1 taken 401002 times.
1157948 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++)
713 756946 (*arg)->split_sum_func2(thd, ref_item_array, fields, arg, true);
714 401002 }
715
716 55214882 void Item_func::update_used_tables() {
717 55214882 used_tables_cache = get_initial_pseudo_tables();
718 55215254 not_null_tables_cache = 0;
719
720
2/2
✓ Branch 0 taken 114228656 times.
✓ Branch 1 taken 55215035 times.
169443691 for (uint i = 0; i < arg_count; i++) {
721 114228656 args[i]->update_used_tables();
722 114228412 used_tables_cache |= args[i]->used_tables();
723
2/2
✓ Branch 0 taken 107790057 times.
✓ Branch 1 taken 6438257 times.
114228314 if (null_on_null) not_null_tables_cache |= args[i]->not_null_tables();
724 114227907 add_accum_properties(args[i]);
725 }
726 55215035 }
727
728 1443092 void Item_func::print(const THD *thd, String *str,
729 enum_query_type query_type) const {
730
1/2
✓ Branch 0 taken 1443092 times.
✗ Branch 1 not taken.
1443092 str->append(func_name());
731 1443092 str->append('(');
732 1443092 print_args(thd, str, 0, query_type);
733 1443092 str->append(')');
734 1443092 }
735
736 1495452 void Item_func::print_args(const THD *thd, String *str, uint from,
737 enum_query_type query_type) const {
738
2/2
✓ Branch 0 taken 3240063 times.
✓ Branch 1 taken 1495452 times.
4735515 for (uint i = from; i < arg_count; i++) {
739
2/2
✓ Branch 0 taken 1834055 times.
✓ Branch 1 taken 1406008 times.
3240063 if (i != from) str->append(',');
740 3240063 args[i]->print(thd, str, query_type);
741 }
742 1495452 }
743
744 1012711 void Item_func::print_op(const THD *thd, String *str,
745 enum_query_type query_type) const {
746 1012711 str->append('(');
747
2/2
✓ Branch 0 taken 1012711 times.
✓ Branch 1 taken 1012711 times.
2025422 for (uint i = 0; i < arg_count - 1; i++) {
748 1012711 args[i]->print(thd, str, query_type);
749 1012711 str->append(' ');
750
1/2
✓ Branch 0 taken 1012711 times.
✗ Branch 1 not taken.
1012711 str->append(func_name());
751 1012711 str->append(' ');
752 }
753 1012711 args[arg_count - 1]->print(thd, str, query_type);
754 1012711 str->append(')');
755 1012711 }
756
757 /// @note Please keep in sync with Item_sum::eq().
758 409500 bool Item_func::eq(const Item *item, bool binary_cmp) const {
759 /* Assume we don't have rtti */
760
2/2
✓ Branch 0 taken 70110 times.
✓ Branch 1 taken 339390 times.
409500 if (this == item) return true;
761
2/2
✓ Branch 0 taken 134554 times.
✓ Branch 1 taken 204836 times.
339390 if (item->type() != FUNC_ITEM) return false;
762 204836 const Item_func *item_func = down_cast<const Item_func *>(item);
763 Item_func::Functype func_type;
764 204836 if ((func_type = functype()) != item_func->functype() ||
765
4/4
✓ Branch 0 taken 121057 times.
✓ Branch 1 taken 336 times.
✓ Branch 2 taken 120711 times.
✓ Branch 3 taken 346 times.
121393 arg_count != item_func->arg_count ||
766 120711 (func_type != Item_func::FUNC_SP &&
767
8/8
✓ Branch 0 taken 121393 times.
✓ Branch 1 taken 83443 times.
✓ Branch 2 taken 118067 times.
✓ Branch 3 taken 2644 times.
✓ Branch 4 taken 346 times.
✓ Branch 5 taken 118067 times.
✓ Branch 6 taken 86599 times.
✓ Branch 7 taken 118237 times.
326575 strcmp(func_name(), item_func->func_name()) != 0) ||
768 346 (func_type == Item_func::FUNC_SP &&
769
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 170 times.
346 my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
770 86599 return false;
771 118237 return AllItemsAreEqual(args, item_func->args, arg_count, binary_cmp);
772 }
773
774 55353 Field *Item_func::tmp_table_field(TABLE *table) {
775 55353 Field *field = nullptr;
776
777
3/5
✓ Branch 0 taken 5836 times.
✓ Branch 1 taken 127 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49390 times.
✗ Branch 4 not taken.
55353 switch (result_type()) {
778 5836 case INT_RESULT:
779
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5835 times.
5836 if (this->data_type() == MYSQL_TYPE_YEAR)
780
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 field = new (*THR_MALLOC) Field_year(is_nullable(), item_name.ptr());
781
2/2
✓ Branch 0 taken 2171 times.
✓ Branch 1 taken 3664 times.
5835 else if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
782
1/2
✓ Branch 0 taken 2171 times.
✗ Branch 1 not taken.
6513 field = new (*THR_MALLOC) Field_longlong(
783
1/2
✓ Branch 0 taken 2171 times.
✗ Branch 1 not taken.
6513 max_length, is_nullable(), item_name.ptr(), unsigned_flag);
784 else
785
1/2
✓ Branch 0 taken 3664 times.
✗ Branch 1 not taken.
14656 field = new (*THR_MALLOC) Field_long(max_length, is_nullable(),
786
1/2
✓ Branch 0 taken 3664 times.
✗ Branch 1 not taken.
10992 item_name.ptr(), unsigned_flag);
787 5836 break;
788 127 case REAL_RESULT:
789
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 124 times.
127 if (this->data_type() == MYSQL_TYPE_FLOAT) {
790
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
9 field = new (*THR_MALLOC)
791 3 Field_float(max_char_length(), is_nullable(), item_name.ptr(),
792
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 decimals, unsigned_flag);
793 } else {
794
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
372 field = new (*THR_MALLOC)
795 124 Field_double(max_char_length(), is_nullable(), item_name.ptr(),
796
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
248 decimals, unsigned_flag);
797 }
798 127 break;
799 case STRING_RESULT:
800 return make_string_field(table);
801 break;
802 49390 case DECIMAL_RESULT:
803 49390 field = Field_new_decimal::create_from_item(this);
804 49390 break;
805 case ROW_RESULT:
806 default:
807 // This case should never be chosen
808 assert(0);
809 field = nullptr;
810 break;
811 }
812
1/2
✓ Branch 0 taken 55353 times.
✗ Branch 1 not taken.
55353 if (field) field->init(table);
813 55353 return field;
814 }
815
816 1306390 my_decimal *Item_func::val_decimal(my_decimal *decimal_value) {
817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1306390 times.
1306390 assert(fixed);
818 1306390 longlong nr = val_int();
819
2/2
✓ Branch 0 taken 572066 times.
✓ Branch 1 taken 734324 times.
1306390 if (null_value) return nullptr; /* purecov: inspected */
820 734324 int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value);
821 734324 return decimal_value;
822 }
823
824 518286 String *Item_real_func::val_str(String *str) {
825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 518286 times.
518286 assert(fixed == 1);
826 518286 double nr = val_real();
827
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 518176 times.
518185 if (null_value) return nullptr; /* purecov: inspected */
828 518176 str->set_real(nr, decimals, collation.collation);
829 520741 return str;
830 }
831
832 12 my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value) {
833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 assert(fixed);
834 12 double nr = val_real();
835
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (null_value) return nullptr; /* purecov: inspected */
836 5 double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value);
837 5 return decimal_value;
838 }
839
840 96 void Item_func::fix_num_length_and_dec() {
841 96 uint fl_length = 0;
842 96 decimals = 0;
843
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 96 times.
208 for (uint i = 0; i < arg_count; i++) {
844 112 decimals = max(decimals, args[i]->decimals);
845 112 fl_length = max(fl_length, args[i]->max_length);
846 }
847 96 max_length = float_length(decimals);
848
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 94 times.
96 if (fl_length > max_length) {
849 2 decimals = DECIMAL_NOT_SPECIFIED;
850 2 max_length = float_length(DECIMAL_NOT_SPECIFIED);
851 }
852 96 }
853
854 2619937 void Item_func_numhybrid::fix_num_length_and_dec() {}
855
856 15189 void Item_func::signal_divide_by_null() {
857 15189 THD *thd = current_thd;
858
2/2
✓ Branch 0 taken 10996 times.
✓ Branch 1 taken 4193 times.
15189 if (thd->variables.sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
859 10996 push_warning(thd, Sql_condition::SL_WARNING, ER_DIVISION_BY_ZERO,
860 ER_THD(thd, ER_DIVISION_BY_ZERO));
861 15189 null_value = true;
862 15189 }
863
864 60 void Item_func::signal_invalid_argument_for_log() {
865 60 THD *thd = current_thd;
866 60 push_warning(thd, Sql_condition::SL_WARNING,
867 ER_INVALID_ARGUMENT_FOR_LOGARITHM,
868 ER_THD(thd, ER_INVALID_ARGUMENT_FOR_LOGARITHM));
869 60 null_value = true;
870 60 }
871
872 56196 Item *Item_func::get_tmp_table_item(THD *thd) {
873
1/2
✓ Branch 0 taken 56196 times.
✗ Branch 1 not taken.
56196 DBUG_TRACE;
874
875 /*
876 For items with aggregate functions, return the copy
877 of the function.
878 For constant items, return the same object, as fields
879 are not created in temp tables for them.
880 For items with windowing functions, return the same
881 object (temp table fields are not created for windowing
882 functions if they are not evaluated at this stage).
883 */
884
6/6
✓ Branch 0 taken 55852 times.
✓ Branch 1 taken 344 times.
✓ Branch 2 taken 55750 times.
✓ Branch 3 taken 102 times.
✓ Branch 4 taken 54280 times.
✓ Branch 5 taken 1916 times.
111946 if (!has_aggregation() && !has_wf() &&
885
3/4
✓ Branch 0 taken 55750 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1470 times.
✓ Branch 3 taken 54280 times.
55750 !(const_for_execution() &&
886
2/4
✓ Branch 0 taken 1470 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1470 times.
1470 evaluate_during_optimization(this, thd->lex->current_query_block()))) {
887
2/4
✓ Branch 0 taken 54280 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54280 times.
✗ Branch 3 not taken.
54280 Item *result = new Item_field(result_field);
888 54280 return result;
889 }
890
1/2
✓ Branch 0 taken 1916 times.
✗ Branch 1 not taken.
1916 Item *result = copy_or_same(thd);
891 1916 return result;
892 56196 }
893
894 62968560 const Item_field *Item_func::contributes_to_filter(
895 table_map read_tables, table_map filter_for_table,
896 const MY_BITMAP *fields_to_ignore) const {
897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62968560 times.
62968560 assert((read_tables & filter_for_table) == 0);
898 /*
899 Multiple equality (Item_equal) should not call this function
900 because it would reject valid comparisons.
901 */
902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62968786 times.
62968560 assert(functype() != MULT_EQUAL_FUNC);
903
904 /*
905 To contribute to filtering effect, the condition must refer to
906 exactly one unread table: the table filtering is currently
907 calculated for.
908 */
909
2/2
✓ Branch 0 taken 53894945 times.
✓ Branch 1 taken 9073829 times.
62968786 if ((used_tables() & ~read_tables) != filter_for_table) return nullptr;
910
911 /*
912 Whether or not this Item_func has an operand that is a field in
913 'filter_for_table' that is not in 'fields_to_ignore'.
914 */
915 9073829 Item_field *usable_field = nullptr;
916
917 /*
918 Whether or not this Item_func has an operand that can be used as
919 available value. arg_count==1 for Items with implicit values like
920 "field IS NULL".
921 */
922 9073829 bool found_comparable = (arg_count == 1);
923
924
2/2
✓ Branch 0 taken 18104932 times.
✓ Branch 1 taken 9073660 times.
27178592 for (uint i = 0; i < arg_count; i++) {
925 18104932 const Item::Type arg_type = args[i]->real_item()->type();
926
927
2/2
✓ Branch 0 taken 734 times.
✓ Branch 1 taken 18104250 times.
18104984 if (arg_type == Item::SUBSELECT_ITEM) {
928
2/2
✓ Branch 0 taken 490 times.
✓ Branch 1 taken 244 times.
734 if (args[i]->const_for_execution()) {
929 // Constant subquery, i.e., not a dependent subquery.
930 490 found_comparable = true;
931 490 continue;
932 }
933
934 /*
935 This is either "fld OP <dependent_subquery>" or "fld BETWEEN X
936 and Y" where either X or Y is a dependent subquery. Filtering
937 effect should not be calculated for this item because the cost
938 of evaluating the dependent subquery is currently not
939 calculated and its accompanying filtering effect is too
940 uncertain. See WL#7384.
941 */
942 244 return nullptr;
943 } // ... if subquery.
944
945 18104250 const table_map used_tabs = args[i]->used_tables();
946
947
4/4
✓ Branch 0 taken 3720074 times.
✓ Branch 1 taken 14384199 times.
✓ Branch 2 taken 3671406 times.
✓ Branch 3 taken 48668 times.
18104273 if (arg_type == Item::FIELD_ITEM && (used_tabs == filter_for_table)) {
948 /*
949 The qualifying table of args[i] is filter_for_table. args[i]
950 may be a field or a reference to a field, e.g. through a
951 view.
952 */
953 3671406 Item_field *fld = static_cast<Item_field *>(args[i]->real_item());
954
955 /*
956 Use args[i] as value if
957 1) this field shall be ignored, or
958 2) a usable field has already been found (meaning that
959 this is "filter_for_table.colX OP filter_for_table.colY").
960 */
961
6/6
✓ Branch 0 taken 3634850 times.
✓ Branch 1 taken 36556 times.
✓ Branch 2 taken 1149 times.
✓ Branch 3 taken 3633701 times.
✓ Branch 4 taken 37705 times.
✓ Branch 5 taken 3633701 times.
3671406 if (bitmap_is_set(fields_to_ignore, fld->field->field_index()) || // 1)
962 usable_field) // 2)
963 {
964 37705 found_comparable = true;
965 37705 continue;
966 }
967
968 /*
969 This field shall contribute to filtering effect if a
970 value is found for it
971 */
972 3633701 usable_field = fld;
973 3633701 } // if field.
974 else {
975 /*
976 It's not a subquery. May be a function, a constant, an outer
977 reference, a field of another table...
978
979 Already checked that this predicate does not refer to tables
980 later in the join sequence. Verify it:
981 */
982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14432867 times.
14432867 assert(!(used_tabs & (~read_tables & ~filter_for_table)));
983 14432867 found_comparable = true;
984 }
985 }
986
1/2
✓ Branch 0 taken 9073664 times.
✗ Branch 1 not taken.
9073660 return (found_comparable ? usable_field : nullptr);
987 }
988
989 134186 bool Item_func::is_valid_for_pushdown(uchar *arg) {
990 Condition_pushdown::Derived_table_info *dti =
991 134186 pointer_cast<Condition_pushdown::Derived_table_info *>(arg);
992 // We cannot push conditions that are not deterministic to a
993 // derived table having set operations.
994
4/4
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 133986 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 194 times.
134186 return (dti->is_set_operation() && is_non_deterministic());
995 }
996
997 43 bool Item_func::check_column_in_window_functions(uchar *arg [[maybe_unused]]) {
998 // Pushing conditions having non-deterministic results must be done with
999 // care, or it may result in eliminating rows which would have
1000 // otherwise contributed to aggregations.
1001 // For Ex: SELECT * FROM (SELECT a AS x, SUM(b) FROM t1 GROUP BY a) dt
1002 // WHERE x>5*RAND() AND x<3.
1003 // In this case, x<3 is pushed to the WHERE clause of the derived table
1004 // because there is grouping on "a". If we did the same for the random
1005 // condition, this condition might reduce the number of rows that get
1006 // qualified for grouping, resulting in wrong values for SUM. Similarly for
1007 // window functions. So we refrain from pushing the random condition
1008 // past the last operation done in the derived table's
1009 // materialization. Therefore, if there are window functions we cannot push
1010 // to HAVING, and if there is GROUP BY we cannot push to WHERE.
1011 // See also Item_field::is_valid_for_pushdown().
1012 43 return is_non_deterministic();
1013 }
1014
1015 78 bool Item_func::check_column_in_group_by(uchar *arg [[maybe_unused]]) {
1016 78 return is_non_deterministic();
1017 }
1018
1019 6401397 bool is_function_of_type(const Item *item, Item_func::Functype type) {
1020
2/2
✓ Branch 0 taken 45713 times.
✓ Branch 1 taken 6355684 times.
6447110 return item->type() == Item::FUNC_ITEM &&
1021
2/2
✓ Branch 0 taken 4446 times.
✓ Branch 1 taken 41267 times.
6447110 down_cast<const Item_func *>(item)->functype() == type;
1022 }
1023
1024 105 bool contains_function_of_type(Item *item, Item_func::Functype type) {
1025
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
210 return WalkItem(item, enum_walk::PREFIX, [type](Item *inner_item) {
1026 217 return is_function_of_type(inner_item, type);
1027 210 });
1028 }
1029
1030 /**
1031 Return new Item_field if given expression matches GC
1032
1033 @see substitute_gc()
1034
1035 @param func Expression to be replaced
1036 @param fld GCs field
1037 @param type Result type to match with Field
1038 @param[out] found If given, just return found field, without Item_field
1039
1040 @returns
1041 item new Item_field for matched GC
1042 NULL otherwise
1043 */
1044
1045 1194 Item_field *get_gc_for_expr(const Item *func, Field *fld, Item_result type,
1046 Field **found) {
1047 1194 func = func->real_item();
1048 1194 Item *expr = fld->gcol_info->expr_item;
1049
1050 /*
1051 In the case where the generated column expression returns JSON and
1052 the predicate compares the values as strings, it is not safe to
1053 replace the expression with the generated column, since the
1054 indexed string values will be double-quoted. The generated column
1055 expression should use the JSON_UNQUOTE function to strip off the
1056 double-quotes in order to get a usable index for looking up
1057 strings. See also the comment below.
1058 */
1059
6/6
✓ Branch 0 taken 839 times.
✓ Branch 1 taken 355 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 837 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1192 times.
1194 if (type == STRING_RESULT && expr->data_type() == MYSQL_TYPE_JSON)
1060 2 return nullptr;
1061
1062 /*
1063 In order to match expressions against a functional index's expression,
1064 it's needed to skip CAST(.. AS .. ) and potentially COLLATE from the latter.
1065 This can't be joined with striping json_unquote below, since we might need
1066 to skip it too in expression like:
1067 CAST(JSON_UNQUOTE(<expr>) AS CHAR(X))
1068
1069 Also skip unquoting function. This is needed to address JSON string
1070 comparison issue. All JSON_* functions return quoted strings. In
1071 order to create usable index, GC column expression has to include
1072 JSON_UNQUOTE function, e.g JSON_UNQUOTE(JSON_EXTRACT(..)).
1073 Hence, the unquoting function in column expression have to be
1074 skipped in order to correctly match GC expr to expr in
1075 WHERE condition. The exception is if user has explicitly used
1076 JSON_UNQUOTE in WHERE condition.
1077 */
1078
1079 4768 for (Item_func::Functype functype :
1080 {Item_func::COLLATE_FUNC, Item_func::TYPECAST_FUNC,
1081
2/2
✓ Branch 0 taken 3576 times.
✓ Branch 1 taken 1192 times.
5960 Item_func::JSON_UNQUOTE_FUNC}) {
1082
5/6
✓ Branch 0 taken 3576 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1141 times.
✓ Branch 3 taken 2435 times.
✓ Branch 4 taken 1050 times.
✓ Branch 5 taken 2526 times.
4717 if (is_function_of_type(expr, functype) &&
1083
3/4
✓ Branch 0 taken 1141 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1050 times.
✓ Branch 3 taken 91 times.
1141 !is_function_of_type(func, functype)) {
1084
1/2
✓ Branch 0 taken 1050 times.
✗ Branch 1 not taken.
1050 expr = down_cast<Item_func *>(expr)->get_arg(0);
1085 }
1086 }
1087
1088
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1191 times.
1192 if (!expr->can_be_substituted_for_gc(fld->is_array())) {
1089 1 return nullptr;
1090 }
1091
1092 // JSON implementation always uses binary collation
1093 1191 bool bin_cmp = (expr->data_type() == MYSQL_TYPE_JSON);
1094
6/6
✓ Branch 0 taken 1074 times.
✓ Branch 1 taken 117 times.
✓ Branch 2 taken 883 times.
✓ Branch 3 taken 191 times.
✓ Branch 4 taken 883 times.
✓ Branch 5 taken 308 times.
1191 if (type == fld->result_type() && func->eq(expr, bin_cmp)) {
1095
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 645 times.
883 if (found) {
1096 // Temporary mark the field in order to check correct value conversion
1097 238 fld->table->mark_column_used(fld, MARK_COLUMNS_TEMP);
1098 238 *found = fld;
1099 238 return nullptr;
1100 }
1101 // Mark field for read
1102 645 fld->table->mark_column_used(fld, MARK_COLUMNS_READ);
1103
2/4
✓ Branch 0 taken 645 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 645 times.
✗ Branch 3 not taken.
645 Item_field *field = new Item_field(fld);
1104 645 return field;
1105 }
1106
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 259 times.
308 if (found) *found = nullptr;
1107 308 return nullptr;
1108 }
1109
1110 /**
1111 Attempt to substitute an expression with an equivalent generated
1112 column in a predicate.
1113
1114 @param expr the expression that should be substituted
1115 @param value if given, value will be coerced to GC field's type and
1116 the result will substitute the original value. Used by
1117 multi-valued index.
1118 @param gc_fields list of indexed generated columns to check for
1119 equivalence with the expression
1120 @param type the acceptable type of the generated column that
1121 replaces the expression
1122 @param predicate the predicate in which the substitution is done
1123
1124 @return true on error, false on success
1125 */
1126 797 static bool substitute_gc_expression(Item **expr, Item **value,
1127 List<Field> *gc_fields, Item_result type,
1128 Item_func *predicate) {
1129
1/2
✓ Branch 0 taken 797 times.
✗ Branch 1 not taken.
797 List_iterator<Field> li(*gc_fields);
1130 797 Item_field *item_field = nullptr;
1131
2/2
✓ Branch 0 taken 917 times.
✓ Branch 1 taken 153 times.
1070 while (Field *field = li++) {
1132 // Check whether the field has usable keys.
1133 917 Key_map tkm = field->part_of_key;
1134 917 tkm.merge(field->part_of_prefixkey); // Include prefix keys.
1135 917 tkm.intersect(field->table->keys_in_use_for_query);
1136 /*
1137 Don't substitute if:
1138 1) Key is disabled
1139 2) It's a multi-valued index's field and predicate isn't MEMBER OF
1140 */
1141
4/4
✓ Branch 0 taken 903 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 899 times.
1820 if (tkm.is_clear_all() || // (1)
1142
6/8
✓ Branch 0 taken 903 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 552 times.
✓ Branch 3 taken 351 times.
✓ Branch 4 taken 552 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 548 times.
903 (field->is_array() && predicate->functype() != // (2)
1143 Item_func::MEMBER_OF_FUNC))
1144 18 continue;
1145 // If the field is a hidden field used by a functional index, we require
1146 // that the collation of the field must match the collation of the
1147 // expression. If not, we might end up with the wrong result when using
1148 // the index (see bug#27337092). Ideally, this should be done for normal
1149 // generated columns as well, but that is delayed to a later fix since the
1150 // impact might be quite large.
1151
4/4
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 282 times.
✓ Branch 2 taken 894 times.
✓ Branch 3 taken 5 times.
1516 if (!(field->is_field_for_functional_index() &&
1152
3/4
✓ Branch 0 taken 617 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 599 times.
617 field->match_collation_to_optimize_range() &&
1153
3/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 5 times.
18 (*expr)->collation.collation != field->charset())) {
1154
1/2
✓ Branch 0 taken 894 times.
✗ Branch 1 not taken.
894 item_field = get_gc_for_expr(*expr, field, type);
1155
2/2
✓ Branch 0 taken 644 times.
✓ Branch 1 taken 250 times.
894 if (item_field != nullptr) break;
1156 }
1157 273 }
1158
1159
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 644 times.
797 if (item_field == nullptr) return false;
1160
1161 // A matching expression is found. Substitute the expression with
1162 // the matching generated column.
1163
1/2
✓ Branch 0 taken 644 times.
✗ Branch 1 not taken.
644 THD *thd = current_thd;
1164
6/8
✓ Branch 0 taken 644 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 464 times.
✓ Branch 3 taken 180 times.
✓ Branch 4 taken 464 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 464 times.
✓ Branch 7 taken 180 times.
644 if (item_field->returns_array() && value) {
1165 464 Json_wrapper wr;
1166 464 String str_val, buf;
1167 464 Field_typed_array *afld = down_cast<Field_typed_array *>(item_field->field);
1168
1169
1/2
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
464 Functional_index_error_handler functional_index_error_handler(afld, thd);
1170
1171
2/4
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 464 times.
464 if (get_json_atom_wrapper(value, 0, "MEMBER OF", &str_val, &buf, &wr,
1172 nullptr, true))
1173 return true;
1174
1175 464 auto to_wr = make_unique_destroy_only<Json_wrapper>(thd->mem_root);
1176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
464 if (to_wr == nullptr) return true;
1177
1178 // Don't substitute if value can't be coerced to field's type
1179
3/4
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 462 times.
464 if (afld->coerce_json_value(&wr, /*no_error=*/true, to_wr.get()))
1180 2 return false;
1181
1182 Item_json *jsn =
1183
2/4
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 462 times.
✗ Branch 3 not taken.
462 new (thd->mem_root) Item_json(std::move(to_wr), predicate->item_name);
1184
4/8
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 462 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 462 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 462 times.
462 if (jsn == nullptr || jsn->fix_fields(thd, nullptr)) return true;
1185
1/2
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
462 thd->change_item_tree(value, jsn);
1186
10/10
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 462 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 462 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 462 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 462 times.
✓ Branch 9 taken 2 times.
472 }
1187
1/2
✓ Branch 0 taken 642 times.
✗ Branch 1 not taken.
642 thd->change_item_tree(expr, item_field);
1188
1189 // Adjust the predicate.
1190
1/2
✓ Branch 0 taken 642 times.
✗ Branch 1 not taken.
642 return predicate->resolve_type(thd);
1191 }
1192
1193 /**
1194 A helper function for Item_func::gc_subst_transformer, that tries to
1195 substitute the given JSON_CONTAINS or JSON_OVERLAPS function for one of GCs
1196 from the provided list. The function checks whether there's an index with
1197 matching expression and whether all scalars for lookup can be coerced to
1198 index's GC field without errors. If so, index's GC field substitutes the
1199 given function, args are replaced for array of coerced values in order to
1200 match GC's type. substitute_gc_expression() can't be used to these functions
1201 as it's tailored to handle regular single-valued indexes and doesn't ensure
1202 correct coercion of all values to lookup in multi-valued index.
1203
1204 @param func Function to replace
1205 @param vals Args to replace
1206 @param vals_wr Json_wrapper containing array of values for index lookup
1207 @param gc_fields List of generated fields to look the function's substitute in
1208 */
1209
1210 261 static void gc_subst_overlaps_contains(Item **func, Item **vals,
1211 Json_wrapper &vals_wr,
1212 List<Field> *gc_fields) {
1213 // Field to substitute function for. NULL when no matching index was found.
1214 261 Field *found = nullptr;
1215
4/8
✓ Branch 0 taken 261 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 261 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 261 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 261 times.
✗ Branch 7 not taken.
261 assert(vals_wr.type() != enum_json_type::J_OBJECT &&
1216 vals_wr.type() != enum_json_type::J_ERROR);
1217
1/2
✓ Branch 0 taken 261 times.
✗ Branch 1 not taken.
261 THD *thd = current_thd;
1218 // Vector of coerced keys
1219
1/2
✓ Branch 0 taken 261 times.
✗ Branch 1 not taken.
261 Json_array_ptr coerced_keys = create_dom_ptr<Json_array>();
1220
1221 // Find a field that matches the expression
1222
5/8
✓ Branch 0 taken 261 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 261 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 399 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 373 times.
✓ Branch 7 taken 26 times.
399 for (Field &fld : *gc_fields) {
1223 373 bool can_use_index = true;
1224 // Check whether field has usable keys
1225 373 Key_map tkm = fld.part_of_key;
1226 373 tkm.intersect(fld.table->keys_in_use_for_query);
1227
1228
7/8
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 360 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 287 times.
✓ Branch 6 taken 86 times.
✓ Branch 7 taken 287 times.
422 if (tkm.is_clear_all() || !fld.is_array()) continue;
1229
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 Functional_index_error_handler func_idx_err_hndl(&fld, thd);
1230 287 found = nullptr;
1231
1232
2/4
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 287 times.
✗ Branch 3 not taken.
287 get_gc_for_expr(*func, &fld, fld.result_type(), &found);
1233
6/8
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 238 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 238 times.
✓ Branch 6 taken 49 times.
✓ Branch 7 taken 238 times.
287 if (!found || !found->is_array()) continue;
1234 238 Field_typed_array *afld = down_cast<Field_typed_array *>(found);
1235 // Check that array's values can be coerced to found field's type
1236 uint len;
1237
3/4
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 142 times.
✓ Branch 3 taken 96 times.
238 if (vals_wr.type() == enum_json_type::J_ARRAY)
1238
1/2
✓ Branch 0 taken 142 times.
✗ Branch 1 not taken.
142 len = vals_wr.length();
1239 else
1240 96 len = 1;
1241 238 coerced_keys->clear();
1242
2/2
✓ Branch 0 taken 381 times.
✓ Branch 1 taken 235 times.
616 for (uint i = 0; i < len; i++) {
1243
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 Json_wrapper elt = vals_wr[i];
1244 381 Json_wrapper res;
1245
3/4
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 378 times.
381 if (afld->coerce_json_value(&elt, true, &res)) {
1246 3 can_use_index = false;
1247 3 found = nullptr;
1248 3 break;
1249 }
1250
2/4
✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 378 times.
✗ Branch 3 not taken.
378 coerced_keys->append_clone(res.to_dom());
1251
4/4
✓ Branch 0 taken 378 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 378 times.
✓ Branch 3 taken 3 times.
384 }
1252
2/2
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 3 times.
238 if (can_use_index) break;
1253
3/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 235 times.
287 }
1254
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 235 times.
261 if (!found) return;
1255 235 TABLE *table = found->table;
1256
2/4
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
235 Item_field *subs_item = new Item_field(found);
1257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235 times.
235 if (!subs_item) return;
1258 auto res = make_unique_destroy_only<Json_wrapper>(thd->mem_root,
1259
1/2
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
235 coerced_keys.release());
1260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235 times.
235 if (res == nullptr) return;
1261 Item_json *array_arg =
1262
2/4
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
235 new (thd->mem_root) Item_json(std::move(res), (*func)->item_name);
1263
4/8
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 235 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 235 times.
235 if (!array_arg || array_arg->fix_fields(thd, nullptr)) return;
1264
1/2
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
235 table->mark_column_used(found, MARK_COLUMNS_READ);
1265
1/2
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
235 thd->change_item_tree(func, subs_item);
1266
1/2
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
235 thd->change_item_tree(vals, array_arg);
1267
3/4
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
✓ Branch 3 taken 26 times.
261 }
1268
1269 /**
1270 Transformer function for GC substitution.
1271
1272 @param arg List of indexed GC field
1273
1274 @return this item on successful execution, nullptr on error
1275
1276 @details This function transforms a search condition. It doesn't change
1277 'this' item but rather changes its arguments. It takes list of GC fields
1278 and checks whether arguments of 'this' item matches them and index over
1279 the GC field isn't disabled with hints. If so, it replaces
1280 the argument with newly created Item_field which uses the matched GC field.
1281 The following predicates' arguments could be transformed:
1282 - EQ_FUNC, LT_FUNC, LE_FUNC, GE_FUNC, GT_FUNC, JSON_OVERLAPS
1283 - Left _or_ right argument if the opposite argument is a constant.
1284 - IN_FUNC, BETWEEN
1285 - Left argument if all other arguments are constant and of the same type.
1286 - MEMBER OF
1287 - Right argument if left argument is constant.
1288 - JSON_CONTAINS
1289 - First argument if the second argument is constant.
1290
1291 After transformation comparators are updated to take into account the new
1292 field.
1293
1294 Note: Range optimizer is used with multi-value indexes and it prefers
1295 constants. Outer references are not considered as constants in JSON functions.
1296 However, range optimizer supports dynamic ranges, where ranges are
1297 re-optimized for each row. But the range optimizer is currently not able to
1298 handle multi-valued indexes with dynamic ranges, hence we use only constants
1299 in these cases.
1300
1301 */
1302
1303 7339 Item *Item_func::gc_subst_transformer(uchar *arg) {
1304 7339 List<Field> *gc_fields = pointer_cast<List<Field> *>(arg);
1305
1306 363 auto is_const_or_outer_reference = [](const Item *item) {
1307 363 return ((item->used_tables() & ~(OUTER_REF_TABLE_BIT | INNER_TABLE_BIT)) ==
1308 363 0);
1309 };
1310
1311
7/8
✓ Branch 0 taken 7339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6327 times.
✓ Branch 3 taken 89 times.
✓ Branch 4 taken 481 times.
✓ Branch 5 taken 169 times.
✓ Branch 6 taken 112 times.
✓ Branch 7 taken 161 times.
7339 switch (functype()) {
1312 6327 case EQ_FUNC:
1313 case LT_FUNC:
1314 case LE_FUNC:
1315 case GE_FUNC:
1316 case GT_FUNC: {
1317 6327 Item **func = nullptr;
1318 6327 Item *val = nullptr;
1319
1320 // Check if we can substitute a function with a GC. The
1321 // predicate must be on the form <expr> OP <constant> or
1322 // <constant> OP <expr>.
1323
5/6
✓ Branch 0 taken 6327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 289 times.
✓ Branch 3 taken 6038 times.
✓ Branch 4 taken 287 times.
✓ Branch 5 taken 6040 times.
6616 if (args[0]->can_be_substituted_for_gc() &&
1324
3/4
✓ Branch 0 taken 289 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 287 times.
✓ Branch 3 taken 2 times.
289 is_const_or_outer_reference(args[1])) {
1325 287 func = args;
1326 287 val = args[1];
1327
5/6
✓ Branch 0 taken 6040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 6002 times.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 6021 times.
6078 } else if (args[1]->can_be_substituted_for_gc() &&
1328
3/4
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 19 times.
38 is_const_or_outer_reference(args[0])) {
1329 19 func = args + 1;
1330 19 val = args[0];
1331 } else {
1332 6021 break;
1333 }
1334
1335
3/6
✓ Branch 0 taken 306 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 306 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 306 times.
306 if (substitute_gc_expression(func, nullptr, gc_fields, val->result_type(),
1336 this))
1337 return nullptr; /* purecov: inspected */
1338 306 break;
1339 }
1340 89 case BETWEEN:
1341 case IN_FUNC: {
1342
3/4
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 14 times.
89 if (!args[0]->can_be_substituted_for_gc()) break;
1343
1344 // Can only substitute if all the operands on the right-hand
1345 // side are constants of the same type.
1346
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 Item_result type = args[1]->result_type();
1347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!std::all_of(
1348
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 args + 1, args + arg_count,
1349 72 [type, is_const_or_outer_reference](const Item *item_arg) {
1350
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
72 return is_const_or_outer_reference(item_arg) &&
1351
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
72 item_arg->result_type() == type;
1352 })) {
1353 break;
1354 }
1355
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
14 if (substitute_gc_expression(args, nullptr, gc_fields, type, this))
1356 return nullptr;
1357 14 break;
1358 }
1359 481 case MEMBER_OF_FUNC: {
1360
1/2
✓ Branch 0 taken 481 times.
✗ Branch 1 not taken.
481 Item_result type = args[0]->result_type();
1361 /*
1362 Check whether MEMBER OF is applicable for optimization:
1363 1) 1st arg is constant for execution
1364 2) .. and it isn't NULL, as MEMBER OF can't be used to lookup NULLs
1365 3) 2nd arg can be substituted for a GC
1366 */
1367
1/2
✓ Branch 0 taken 481 times.
✗ Branch 1 not taken.
481 if (args[0]->const_for_execution() && // 1
1368
7/8
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 477 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 477 times.
✓ Branch 7 taken 4 times.
958 !args[0]->is_null() && // 2
1369
2/4
✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
✗ Branch 3 not taken.
477 args[1]->can_be_substituted_for_gc(/*array=*/true)) { // 3
1370
2/4
✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 477 times.
477 if (substitute_gc_expression(args + 1, args, gc_fields, type, this))
1371 return nullptr;
1372 }
1373 481 break;
1374 }
1375 169 case JSON_CONTAINS: {
1376 169 Json_wrapper vals_wr;
1377 169 String str;
1378 /*
1379 Check whether JSON_CONTAINS is applicable for optimization:
1380 1) 1st arg can be substituted with a generated column
1381 2) value to lookup is constant for execution
1382 3) value to lookup is a proper JSON doc
1383 4) value to lookup is an array or scalar
1384 */
1385
4/6
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 156 times.
338 if (!args[0]->can_be_substituted_for_gc(/*array=*/true) || // 1
1386
3/4
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 156 times.
169 !args[1]->const_for_execution()) // 2
1387 13 break;
1388
4/6
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 156 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 155 times.
156 if (get_json_wrapper(args, 1, &str, func_name(), &vals_wr)) { // 3
1389 1 return nullptr;
1390 }
1391
3/4
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 151 times.
310 if (args[1]->null_value ||
1392
3/4
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 151 times.
155 vals_wr.type() == enum_json_type::J_OBJECT) // 4
1393 4 break;
1394
1/2
✓ Branch 0 taken 151 times.
✗ Branch 1 not taken.
151 gc_subst_overlaps_contains(args, args + 1, vals_wr, gc_fields);
1395 151 break;
1396
4/4
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 1 times.
338 }
1397 112 case JSON_OVERLAPS: {
1398 112 Item **func = nullptr;
1399 112 int vals = -1;
1400
1401 /*
1402 Check whether JSON_OVERLAPS is applicable for optimization:
1403 1) One argument is constant for execution
1404 2) The other argument can be substituted with a generated column
1405 3) value to lookup is a proper JSON doc
1406 4) value to lookup is an array or scalar
1407 */
1408
5/6
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 91 times.
✓ Branch 5 taken 21 times.
216 if (args[0]->can_be_substituted_for_gc(/*array=*/true) && // 2
1409
3/4
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 13 times.
104 args[1]->const_for_execution()) { // 1
1410 91 func = args;
1411 91 vals = 1;
1412
3/6
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
42 } else if (args[1]->can_be_substituted_for_gc(/*array=*/true) && // 2
1413
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 args[0]->const_for_execution()) { // 1
1414 21 func = args + 1;
1415 21 vals = 0;
1416 } else {
1417 111 break;
1418 }
1419
1420 112 Json_wrapper vals_wr;
1421 112 String str;
1422
4/6
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 111 times.
112 if (get_json_wrapper(args, vals, &str, func_name(), &vals_wr)) { // 3
1423 1 return nullptr;
1424 }
1425
3/4
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 110 times.
222 if (args[vals]->null_value ||
1426
3/4
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 110 times.
111 vals_wr.type() == enum_json_type::J_OBJECT) // 4
1427 1 break;
1428
1/2
✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
110 gc_subst_overlaps_contains(func, args + vals, vals_wr, gc_fields);
1429 110 break;
1430
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 111 times.
✓ Branch 2 taken 111 times.
✓ Branch 3 taken 1 times.
224 }
1431 161 default:
1432 161 break;
1433 }
1434 7337 return this;
1435 }
1436
1437 854 double Item_int_func::val_real() {
1438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 854 times.
854 assert(fixed == 1);
1439
1440
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 850 times.
854 return unsigned_flag ? (double)((ulonglong)val_int()) : (double)val_int();
1441 }
1442
1443 4024 String *Item_int_func::val_str(String *str) {
1444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4024 times.
4024 assert(fixed == 1);
1445 4024 longlong nr = val_int();
1446
2/2
✓ Branch 0 taken 365 times.
✓ Branch 1 taken 3659 times.
4024 if (null_value) return nullptr;
1447 3659 str->set_int(nr, unsigned_flag, collation.collation);
1448 3659 return str;
1449 }
1450
1451 10214 bool Item_func_connection_id::itemize(Parse_context *pc, Item **res) {
1452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10214 times.
10214 if (skip_itemize(res)) return false;
1453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10215 times.
10214 if (super::itemize(pc, res)) return true;
1454 10215 pc->thd->lex->safe_to_cache_query = false;
1455 10215 return false;
1456 }
1457
1458 2398 bool Item_func_connection_id::resolve_type(THD *thd) {
1459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2398 times.
2398 if (Item_int_func::resolve_type(thd)) return true;
1460 2398 unsigned_flag = true;
1461 2398 return false;
1462 }
1463
1464 2397 bool Item_func_connection_id::fix_fields(THD *thd, Item **ref) {
1465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2398 times.
2397 if (Item_int_func::fix_fields(thd, ref)) return true;
1466 2398 thd->thread_specific_used = true;
1467 2398 return false;
1468 }
1469
1470 6257 longlong Item_func_connection_id::val_int() {
1471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6257 times.
6257 assert(fixed);
1472 6257 return current_thd->variables.pseudo_thread_id;
1473 }
1474
1475 /**
1476 Check arguments to determine the data type for a numeric
1477 function of two arguments.
1478 */
1479
1480 2583631 void Item_num_op::set_numeric_type(void) {
1481
1/2
✓ Branch 0 taken 2583663 times.
✗ Branch 1 not taken.
2583631 DBUG_TRACE;
1482
3/10
✓ Branch 0 taken 2583655 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2583660 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2583660 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
2583663 DBUG_PRINT("info", ("name %s", func_name()));
1483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2583658 times.
2583658 assert(arg_count == 2);
1484
1/2
✓ Branch 0 taken 2583656 times.
✗ Branch 1 not taken.
2583658 Item_result r0 = args[0]->numeric_context_result_type();
1485
1/2
✓ Branch 0 taken 2583647 times.
✗ Branch 1 not taken.
2583656 Item_result r1 = args[1]->numeric_context_result_type();
1486
1487
2/4
✓ Branch 0 taken 2583649 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2583652 times.
✗ Branch 3 not taken.
2583647 assert(r0 != STRING_RESULT && r1 != STRING_RESULT);
1488
1489
4/4
✓ Branch 0 taken 2467950 times.
✓ Branch 1 taken 115702 times.
✓ Branch 2 taken 43827 times.
✓ Branch 3 taken 2424123 times.
2583652 if (r0 == REAL_RESULT || r1 == REAL_RESULT) {
1490 /*
1491 Since DATE/TIME/DATETIME data types return INT_RESULT/DECIMAL_RESULT
1492 type codes, we should never get to here when both fields are temporal.
1493 */
1494
3/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 159448 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
159529 assert(!args[0]->is_temporal() || !args[1]->is_temporal());
1495 159514 set_data_type(MYSQL_TYPE_DOUBLE);
1496 159514 hybrid_type = REAL_RESULT;
1497
1/2
✓ Branch 0 taken 159514 times.
✗ Branch 1 not taken.
159514 aggregate_float_properties(args, arg_count);
1498 159514 max_length = float_length(decimals);
1499
4/4
✓ Branch 0 taken 2313699 times.
✓ Branch 1 taken 110424 times.
✓ Branch 2 taken 20663 times.
✓ Branch 3 taken 2293036 times.
2424123 } else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT) {
1500 131087 set_data_type(MYSQL_TYPE_NEWDECIMAL);
1501 131094 hybrid_type = DECIMAL_RESULT;
1502
1/2
✓ Branch 0 taken 131090 times.
✗ Branch 1 not taken.
131094 result_precision();
1503 } else {
1504
4/4
✓ Branch 0 taken 2293031 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2293030 times.
✓ Branch 3 taken 1 times.
2293036 assert(r0 == INT_RESULT && r1 == INT_RESULT);
1505 2293030 set_data_type(MYSQL_TYPE_LONGLONG);
1506 2293032 decimals = 0;
1507 2293032 hybrid_type = INT_RESULT;
1508
1/2
✓ Branch 0 taken 2293037 times.
✗ Branch 1 not taken.
2293032 result_precision();
1509 }
1510
3/14
✓ Branch 0 taken 2583644 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2583645 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2583645 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
2583641 DBUG_PRINT("info", ("Type: %s", (hybrid_type == REAL_RESULT
1511 ? "REAL_RESULT"
1512 : hybrid_type == DECIMAL_RESULT
1513 ? "DECIMAL_RESULT"
1514 : hybrid_type == INT_RESULT
1515 ? "INT_RESULT"
1516 : "--ILLEGAL!!!--")));
1517 2583645 }
1518
1519 /**
1520 Set data type for a numeric function with one argument
1521 (can be also used by a numeric function with many arguments, if the result
1522 type depends only on the first argument)
1523 */
1524
1525 186641 void Item_func_num1::set_numeric_type() {
1526
1/2
✓ Branch 0 taken 186641 times.
✗ Branch 1 not taken.
186641 DBUG_TRACE;
1527
3/10
✓ Branch 0 taken 186641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 186641 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 186641 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
186641 DBUG_PRINT("info", ("name %s", func_name()));
1528
4/6
✓ Branch 0 taken 186641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182806 times.
✓ Branch 3 taken 1890 times.
✓ Branch 4 taken 1945 times.
✗ Branch 5 not taken.
186641 switch (hybrid_type = args[0]->result_type()) {
1529 182806 case INT_RESULT:
1530 182806 set_data_type(MYSQL_TYPE_LONGLONG);
1531 182806 unsigned_flag = args[0]->unsigned_flag;
1532 182806 break;
1533 1890 case STRING_RESULT:
1534 case REAL_RESULT:
1535 1890 set_data_type(MYSQL_TYPE_DOUBLE);
1536 1890 hybrid_type = REAL_RESULT;
1537 1890 max_length = float_length(decimals);
1538 1890 break;
1539 1945 case DECIMAL_RESULT:
1540 1945 set_data_type(MYSQL_TYPE_NEWDECIMAL);
1541 1945 unsigned_flag = args[0]->unsigned_flag;
1542 1945 break;
1543 default:
1544 assert(0);
1545 }
1546
3/14
✓ Branch 0 taken 186641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 186641 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 186641 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
186641 DBUG_PRINT("info", ("Type: %s", (hybrid_type == REAL_RESULT
1547 ? "REAL_RESULT"
1548 : hybrid_type == DECIMAL_RESULT
1549 ? "DECIMAL_RESULT"
1550 : hybrid_type == INT_RESULT
1551 ? "INT_RESULT"
1552 : "--ILLEGAL!!!--")));
1553 186641 }
1554
1555 9390 void Item_func_num1::fix_num_length_and_dec() {
1556 9390 decimals = args[0]->decimals;
1557 9390 max_length = args[0]->max_length;
1558 9390 }
1559
1560 /*
1561 Reject geometry arguments, should be called in resolve_type() for
1562 SQL functions/operators where geometries are not suitable as operands.
1563 */
1564 5995212 bool reject_geometry_args(uint arg_count, Item **args, Item_result_field *me) {
1565 /*
1566 We want to make sure the operands are not GEOMETRY strings because
1567 it's meaningless for them to participate in arithmetic and/or numerical
1568 calculations.
1569
1570 When a variable holds a MySQL Geometry byte string, it is regarded as a
1571 string rather than a MYSQL_TYPE_GEOMETRY, so here we can't catch an illegal
1572 variable argument which was assigned with a geometry.
1573
1574 Item::data_type() requires the item not be of ROW_RESULT, since a row
1575 isn't a field.
1576 */
1577
2/2
✓ Branch 0 taken 10008911 times.
✓ Branch 1 taken 5995126 times.
16004037 for (uint i = 0; i < arg_count; i++) {
1578
6/6
✓ Branch 0 taken 10008759 times.
✓ Branch 1 taken 164 times.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 10008661 times.
✓ Branch 4 taken 104 times.
✓ Branch 5 taken 10008825 times.
20017676 if (args[i]->result_type() != ROW_RESULT &&
1579 10008759 args[i]->data_type() == MYSQL_TYPE_GEOMETRY) {
1580 104 my_error(ER_WRONG_ARGUMENTS, MYF(0), me->func_name());
1581 104 return true;
1582 }
1583 }
1584
1585 5995126 return false;
1586 }
1587
1588 /**
1589 Go through the arguments of a function and check if any of them are
1590 JSON. If a JSON argument is found, raise a warning saying that this
1591 operation is not supported yet. This function is used to notify
1592 users that they are comparing JSON values using a mechanism that has
1593 not yet been updated to use the JSON comparator. JSON values are
1594 typically handled as strings in that case.
1595
1596 @param arg_count the number of arguments
1597 @param args the arguments to go through looking for JSON values
1598 @param msg the message that explains what is not supported
1599 */
1600 41599 void unsupported_json_comparison(size_t arg_count, Item **args,
1601 const char *msg) {
1602
2/2
✓ Branch 0 taken 121840 times.
✓ Branch 1 taken 41587 times.
163427 for (size_t i = 0; i < arg_count; ++i) {
1603
6/6
✓ Branch 0 taken 3876 times.
✓ Branch 1 taken 117964 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 3864 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 121828 times.
125715 if (args[i]->result_type() == STRING_RESULT &&
1604 3876 args[i]->data_type() == MYSQL_TYPE_JSON) {
1605 11 push_warning_printf(current_thd, Sql_condition::SL_WARNING,
1606 ER_NOT_SUPPORTED_YET,
1607 11 ER_THD(current_thd, ER_NOT_SUPPORTED_YET), msg);
1608 11 break;
1609 }
1610 }
1611 41598 }
1612
1613 2871882 bool Item_func_numhybrid::resolve_type(THD *thd) {
1614
3/4
✓ Branch 0 taken 2619941 times.
✓ Branch 1 taken 251941 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2619941 times.
2871882 assert(arg_count == 1 || arg_count == 2);
1615 /*
1616 If no arguments have type information, return and trust
1617 propagate_type() to assign data types later.
1618 If some argument has type information, propagate the same type to
1619 the other argument.
1620 */
1621
2/2
✓ Branch 0 taken 251942 times.
✓ Branch 1 taken 2619940 times.
2871882 if (arg_count == 1) {
1622
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 251931 times.
251942 if (args[0]->data_type() == MYSQL_TYPE_INVALID) return false;
1623 } else {
1624
6/6
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 2619895 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 33 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 2619928 times.
2619991 if (args[0]->data_type() == MYSQL_TYPE_INVALID &&
1625 49 args[1]->data_type() == MYSQL_TYPE_INVALID)
1626 18 return false;
1627
1628
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 2619901 times.
2619928 if (args[0]->data_type() == MYSQL_TYPE_INVALID) {
1629
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
33 if (args[0]->propagate_type(thd, Type_properties(*args[1]))) return true;
1630
2/2
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 2619627 times.
2619901 } else if (args[1]->data_type() == MYSQL_TYPE_INVALID) {
1631
2/4
✓ Branch 0 taken 274 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 274 times.
274 if (args[1]->propagate_type(thd, Type_properties(*args[0]))) return true;
1632 }
1633 }
1634
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2871871 times.
2871865 if (resolve_type_inner(thd)) return true;
1635 2871871 return reject_geometry_args(arg_count, args, this);
1636 }
1637
1638 2806579 bool Item_func_numhybrid::resolve_type_inner(THD *) {
1639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2806592 times.
2806579 assert(args[0]->data_type() != MYSQL_TYPE_INVALID);
1640
3/4
✓ Branch 0 taken 2619955 times.
✓ Branch 1 taken 186637 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2619951 times.
2806592 assert(arg_count == 1 || args[1]->data_type() != MYSQL_TYPE_INVALID);
1641 2806588 fix_num_length_and_dec();
1642 2806578 set_numeric_type();
1643 2806601 return false;
1644 }
1645
1646 8207827 String *Item_func_numhybrid::val_str(String *str) {
1647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8207827 times.
8207827 assert(fixed == 1);
1648
5/5
✓ Branch 0 taken 29183 times.
✓ Branch 1 taken 246332 times.
✓ Branch 2 taken 17494 times.
✓ Branch 3 taken 7914813 times.
✓ Branch 4 taken 5 times.
8207827 switch (hybrid_type) {
1649 29183 case DECIMAL_RESULT: {
1650 29183 my_decimal decimal_value, *val;
1651
3/4
✓ Branch 0 taken 29183 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5257 times.
✓ Branch 3 taken 23926 times.
29183 if (!(val = decimal_op(&decimal_value))) return nullptr; // null is set
1652
1/2
✓ Branch 0 taken 23926 times.
✗ Branch 1 not taken.
23926 my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, false, val);
1653 23926 str->set_charset(collation.collation);
1654
1/2
✓ Branch 0 taken 23926 times.
✗ Branch 1 not taken.
23926 my_decimal2string(E_DEC_FATAL_ERROR, val, str);
1655 23926 break;
1656
2/2
✓ Branch 0 taken 5257 times.
✓ Branch 1 taken 23926 times.
29183 }
1657 246332 case INT_RESULT: {
1658 246332 longlong nr = int_op();
1659
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 246301 times.
246341 if (null_value) return nullptr; /* purecov: inspected */
1660 246301 str->set_int(nr, unsigned_flag, collation.collation);
1661 246304 break;
1662 }
1663 17494 case REAL_RESULT: {
1664 17494 double nr = real_op();
1665
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 17489 times.
17494 if (null_value) return nullptr; /* purecov: inspected */
1666 17489 str->set_real(nr, decimals, collation.collation);
1667 17489 break;
1668 }
1669 7914813 case STRING_RESULT:
1670
4/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 7914747 times.
7914813 switch (data_type()) {
1671 45 case MYSQL_TYPE_DATETIME:
1672 case MYSQL_TYPE_TIMESTAMP:
1673 45 return val_string_from_datetime(str);
1674 16 case MYSQL_TYPE_DATE:
1675 16 return val_string_from_date(str);
1676 5 case MYSQL_TYPE_TIME:
1677 5 return val_string_from_time(str);
1678 7914747 default:
1679 7914747 break;
1680 }
1681 7914747 return str_op(&str_value);
1682 5 default:
1683 5 assert(0);
1684 }
1685 287719 return str;
1686 }
1687
1688 6199417 double Item_func_numhybrid::val_real() {
1689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6199417 times.
6199417 assert(fixed == 1);
1690
4/5
✓ Branch 0 taken 329716 times.
✓ Branch 1 taken 212275 times.
✓ Branch 2 taken 5657409 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
6199417 switch (hybrid_type) {
1691 329716 case DECIMAL_RESULT: {
1692 329716 my_decimal decimal_value, *val;
1693 double result;
1694
3/4
✓ Branch 0 taken 329716 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
✓ Branch 3 taken 329616 times.
329716 if (!(val = decimal_op(&decimal_value))) return 0.0; // null is set
1695
1/2
✓ Branch 0 taken 329616 times.
✗ Branch 1 not taken.
329616 my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
1696 329616 return result;
1697 329716 }
1698 212275 case INT_RESULT: {
1699 212275 longlong result = int_op();
1700
2/2
✓ Branch 0 taken 2285 times.
✓ Branch 1 taken 209990 times.
212275 return unsigned_flag ? (double)((ulonglong)result) : (double)result;
1701 }
1702 5657409 case REAL_RESULT:
1703 5657409 return real_op();
1704 18 case STRING_RESULT: {
1705
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 14 times.
18 switch (data_type()) {
1706 4 case MYSQL_TYPE_TIME:
1707 case MYSQL_TYPE_DATE:
1708 case MYSQL_TYPE_DATETIME:
1709 case MYSQL_TYPE_TIMESTAMP:
1710
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 return val_real_from_decimal();
1711 14 default:
1712 14 break;
1713 }
1714 const char *end_not_used;
1715 int err_not_used;
1716
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 String *res = str_op(&str_value);
1717
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
14 return (res ? my_strntod(res->charset(), res->ptr(), res->length(),
1718 &end_not_used, &err_not_used)
1719 14 : 0.0);
1720 }
1721 default:
1722 assert(0);
1723 }
1724 return 0.0;
1725 }
1726
1727 90678543 longlong Item_func_numhybrid::val_int() {
1728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90678543 times.
90678543 assert(fixed == 1);
1729
4/5
✓ Branch 0 taken 1118859 times.
✓ Branch 1 taken 89516995 times.
✓ Branch 2 taken 42741 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
90678543 switch (hybrid_type) {
1730 1118859 case DECIMAL_RESULT: {
1731 1118859 my_decimal decimal_value, *val;
1732
3/4
✓ Branch 0 taken 1118859 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1118849 times.
1118859 if (!(val = decimal_op(&decimal_value))) return 0; // null is set
1733 longlong result;
1734
1/2
✓ Branch 0 taken 1118849 times.
✗ Branch 1 not taken.
1118849 my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
1735 1118849 return result;
1736 1118859 }
1737 89516995 case INT_RESULT:
1738 89516995 return int_op();
1739 42741 case REAL_RESULT: {
1740 42741 return llrint_with_overflow_check(real_op());
1741 }
1742 5 case STRING_RESULT: {
1743
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
5 switch (data_type()) {
1744 1 case MYSQL_TYPE_DATE:
1745
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return val_int_from_date();
1746 2 case MYSQL_TYPE_DATETIME:
1747 case MYSQL_TYPE_TIMESTAMP:
1748
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return val_int_from_datetime();
1749 1 case MYSQL_TYPE_TIME:
1750
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return val_int_from_time();
1751 1 default:
1752 1 break;
1753 }
1754 int err_not_used;
1755 String *res;
1756
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!(res = str_op(&str_value))) return 0;
1757
1758 1 const char *end = res->ptr() + res->length();
1759 1 const CHARSET_INFO *cs = res->charset();
1760
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used);
1761 }
1762 default:
1763 assert(0);
1764 }
1765 return 0;
1766 }
1767
1768 2528730 my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value) {
1769 2528730 my_decimal *val = decimal_value;
1770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2528730 times.
2528730 assert(fixed == 1);
1771
4/5
✓ Branch 0 taken 2052252 times.
✓ Branch 1 taken 476338 times.
✓ Branch 2 taken 117 times.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
2528730 switch (hybrid_type) {
1772 2052252 case DECIMAL_RESULT:
1773 2052252 val = decimal_op(decimal_value);
1774 2052263 break;
1775 476338 case INT_RESULT: {
1776 476338 longlong result = int_op();
1777 476338 int2my_decimal(E_DEC_FATAL_ERROR, result, unsigned_flag, decimal_value);
1778 476338 break;
1779 }
1780 117 case REAL_RESULT: {
1781 117 double result = real_op();
1782 117 double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
1783 117 break;
1784 }
1785 24 case STRING_RESULT: {
1786
3/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 14 times.
24 switch (data_type()) {
1787 9 case MYSQL_TYPE_DATE:
1788 case MYSQL_TYPE_DATETIME:
1789 case MYSQL_TYPE_TIMESTAMP:
1790 9 return val_decimal_from_date(decimal_value);
1791 1 case MYSQL_TYPE_TIME:
1792 1 return val_decimal_from_time(decimal_value);
1793 14 default:
1794 14 break;
1795 }
1796 String *res;
1797
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 3 times.
14 if (!(res = str_op(&str_value))) return nullptr;
1798
1799 3 str2my_decimal(E_DEC_FATAL_ERROR, res->ptr(), res->length(),
1800 res->charset(), decimal_value);
1801 2 break;
1802 }
1803 case ROW_RESULT:
1804 default:
1805 assert(0);
1806 }
1807 2528720 return val;
1808 }
1809
1810 224 bool Item_func_numhybrid::get_date(MYSQL_TIME *ltime,
1811 my_time_flags_t fuzzydate) {
1812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 assert(fixed == 1);
1813
4/4
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 37 times.
224 switch (data_type()) {
1814 182 case MYSQL_TYPE_DATE:
1815 case MYSQL_TYPE_DATETIME:
1816 case MYSQL_TYPE_TIMESTAMP:
1817 182 return date_op(ltime, fuzzydate);
1818 4 case MYSQL_TYPE_TIME:
1819 4 return get_date_from_time(ltime);
1820 1 case MYSQL_TYPE_YEAR:
1821 1 return get_date_from_int(ltime, fuzzydate);
1822 37 default:
1823 37 return Item::get_date_from_non_temporal(ltime, fuzzydate);
1824 }
1825 }
1826
1827 44 bool Item_func_numhybrid::get_time(MYSQL_TIME *ltime) {
1828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 assert(fixed == 1);
1829
5/5
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 5 times.
44 switch (data_type()) {
1830 20 case MYSQL_TYPE_TIME:
1831 20 return time_op(ltime);
1832 2 case MYSQL_TYPE_DATE:
1833 2 return get_time_from_date(ltime);
1834 16 case MYSQL_TYPE_DATETIME:
1835 case MYSQL_TYPE_TIMESTAMP:
1836 16 return get_time_from_datetime(ltime);
1837 1 case MYSQL_TYPE_YEAR:
1838 1 return get_time_from_int(ltime);
1839 5 default:
1840 5 return Item::get_time_from_non_temporal(ltime);
1841 }
1842 }
1843
1844 126 void Item_typecast_signed::print(const THD *thd, String *str,
1845 enum_query_type query_type) const {
1846 126 str->append(STRING_WITH_LEN("cast("));
1847 126 args[0]->print(thd, str, query_type);
1848 126 str->append(STRING_WITH_LEN(" as signed)"));
1849 126 }
1850
1851 29502 bool Item_typecast_signed::resolve_type(THD *thd) {
1852
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 29501 times.
29502 if (reject_geometry_args(arg_count, args, this)) return true;
1853 29501 return args[0]->propagate_type(thd, MYSQL_TYPE_LONGLONG, false, true);
1854 }
1855
1856 200994 static longlong val_int_from_str(Item *item, bool unsigned_flag,
1857 bool *null_value) {
1858 /*
1859 For a string result, we must first get the string and then convert it
1860 to a longlong
1861 */
1862 200994 StringBuffer<MAX_FIELD_WIDTH> tmp;
1863
1/2
✓ Branch 0 taken 200994 times.
✗ Branch 1 not taken.
200994 const String *res = item->val_str(&tmp);
1864 200994 *null_value = item->null_value;
1865
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 200886 times.
200994 if (*null_value) return 0;
1866
1867 200886 size_t length = res->length();
1868 200886 const char *start = res->ptr();
1869 200886 const char *end = start + length;
1870
1/2
✓ Branch 0 taken 200886 times.
✗ Branch 1 not taken.
200886 return longlong_from_string_with_check(res->charset(), start, end,
1871 200886 unsigned_flag);
1872 200994 }
1873
1874 201205 longlong Item_typecast_signed::val_int() {
1875 longlong value;
1876
1877
6/6
✓ Branch 0 taken 200883 times.
✓ Branch 1 taken 322 times.
✓ Branch 2 taken 174 times.
✓ Branch 3 taken 200709 times.
✓ Branch 4 taken 496 times.
✓ Branch 5 taken 200709 times.
201205 if (args[0]->cast_to_int_type() != STRING_RESULT || args[0]->is_temporal()) {
1878 496 value = args[0]->val_int();
1879 496 null_value = args[0]->null_value;
1880 } else {
1881 200709 value = val_int_from_str(args[0], unsigned_flag, &null_value);
1882 }
1883
1884 #ifndef NDEBUG
1885
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 201110 times.
201205 if (null_value) {
1886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
95 assert(is_nullable());
1887
2/2
✓ Branch 0 taken 200957 times.
✓ Branch 1 taken 153 times.
201110 } else if (value >= 0) {
1888 200957 const int digits = count_digits(static_cast<ulonglong>(value));
1889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200957 times.
200957 assert(digits <= decimal_int_part());
1890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200957 times.
200957 assert(static_cast<unsigned>(digits) <= max_length);
1891 } else {
1892 const int digits =
1893 153 count_digits(ulonglong{0} - static_cast<ulonglong>(value));
1894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 153 times.
153 assert(digits <= decimal_int_part());
1895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 153 times.
153 assert(static_cast<unsigned>(digits) + 1 <= max_length);
1896 }
1897 #endif
1898
1899 201205 return value;
1900 }
1901
1902 12887 void Item_typecast_unsigned::print(const THD *thd, String *str,
1903 enum_query_type query_type) const {
1904 12887 str->append(STRING_WITH_LEN("cast("));
1905 12887 args[0]->print(thd, str, query_type);
1906 12887 str->append(STRING_WITH_LEN(" as unsigned)"));
1907 12887 }
1908
1909 1053226 bool Item_typecast_unsigned::resolve_type(THD *thd) {
1910
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1053225 times.
1053226 if (reject_geometry_args(arg_count, args, this)) return true;
1911 1053225 return args[0]->propagate_type(thd, MYSQL_TYPE_LONGLONG, false, true);
1912 }
1913
1914 773766 longlong Item_typecast_unsigned::val_int() {
1915 773766 longlong value = 0;
1916
1917
3/4
✓ Branch 0 taken 773766 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1000 times.
✓ Branch 3 taken 772766 times.
773766 if (args[0]->cast_to_int_type() == DECIMAL_RESULT) {
1918
1/2
✓ Branch 0 taken 1000 times.
✗ Branch 1 not taken.
1000 my_decimal tmp, *dec = args[0]->val_decimal(&tmp);
1919 1000 null_value = args[0]->null_value;
1920
2/2
✓ Branch 0 taken 993 times.
✓ Branch 1 taken 7 times.
1000 if (!null_value) {
1921
1/2
✓ Branch 0 taken 993 times.
✗ Branch 1 not taken.
993 my_decimal2int(E_DEC_FATAL_ERROR, dec, !dec->sign(), &value);
1922 }
1923
7/8
✓ Branch 0 taken 772766 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 667685 times.
✓ Branch 3 taken 105081 times.
✓ Branch 4 taken 667400 times.
✓ Branch 5 taken 285 times.
✓ Branch 6 taken 772481 times.
✓ Branch 7 taken 285 times.
1441451 } else if (args[0]->cast_to_int_type() != STRING_RESULT ||
1924 667685 args[0]->is_temporal()) {
1925
1/2
✓ Branch 0 taken 772481 times.
✗ Branch 1 not taken.
772481 value = args[0]->val_int();
1926 772481 null_value = args[0]->null_value;
1927 } else {
1928
1/2
✓ Branch 0 taken 285 times.
✗ Branch 1 not taken.
285 value = val_int_from_str(args[0], unsigned_flag, &null_value);
1929 }
1930
1931
3/4
✓ Branch 0 taken 566848 times.
✓ Branch 1 taken 206918 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 566848 times.
773766 assert(!null_value || is_nullable());
1932
3/6
✓ Branch 0 taken 773766 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 773766 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 773766 times.
773766 assert(count_digits(static_cast<ulonglong>(value)) <= decimal_int_part());
1933
1934 773766 return value;
1935 }
1936
1937 500 String *Item_typecast_decimal::val_str(String *str) {
1938
1/2
✓ Branch 0 taken 500 times.
✗ Branch 1 not taken.
500 my_decimal tmp_buf, *tmp = val_decimal(&tmp_buf);
1939
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 438 times.
500 if (null_value) return nullptr;
1940
1/2
✓ Branch 0 taken 438 times.
✗ Branch 1 not taken.
438 my_decimal2string(E_DEC_FATAL_ERROR, tmp, str);
1941 438 return str;
1942 500 }
1943
1944 6 double Item_typecast_decimal::val_real() {
1945
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_decimal tmp_buf, *tmp = val_decimal(&tmp_buf);
1946 double res;
1947
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (null_value) return 0.0;
1948
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_decimal2double(E_DEC_FATAL_ERROR, tmp, &res);
1949 4 return res;
1950 6 }
1951
1952 14 longlong Item_typecast_decimal::val_int() {
1953
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 my_decimal tmp_buf, *tmp = val_decimal(&tmp_buf);
1954 longlong res;
1955
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (null_value) return 0;
1956
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_decimal2int(E_DEC_FATAL_ERROR, tmp, unsigned_flag, &res);
1957 12 return res;
1958 14 }
1959
1960 11374 my_decimal *Item_typecast_decimal::val_decimal(my_decimal *dec) {
1961
1/2
✓ Branch 0 taken 11374 times.
✗ Branch 1 not taken.
11374 my_decimal tmp_buf, *tmp = args[0]->val_decimal(&tmp_buf);
1962 bool sign;
1963 uint precision;
1964
1965
2/2
✓ Branch 0 taken 267 times.
✓ Branch 1 taken 11107 times.
11374 if ((null_value = args[0]->null_value)) return nullptr;
1966
1/2
✓ Branch 0 taken 11107 times.
✗ Branch 1 not taken.
11107 my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, false, dec);
1967 11107 sign = dec->sign();
1968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11107 times.
11107 if (unsigned_flag) {
1969 if (sign) {
1970 my_decimal_set_zero(dec);
1971 goto err;
1972 }
1973 }
1974 precision =
1975 11107 my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
1976
3/4
✓ Branch 0 taken 11107 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 11074 times.
11107 if (precision - decimals < (uint)my_decimal_intg(dec)) {
1977
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 max_my_decimal(dec, precision, decimals);
1978 33 dec->sign(sign);
1979 33 goto err;
1980 }
1981 11074 return dec;
1982
1983 33 err:
1984 33 push_warning_printf(
1985
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 current_thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE,
1986
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 ER_THD(current_thd, ER_WARN_DATA_OUT_OF_RANGE), item_name.ptr(), 1L);
1987 33 return dec;
1988 11374 }
1989
1990 121 void Item_typecast_decimal::print(const THD *thd, String *str,
1991 enum_query_type query_type) const {
1992 uint precision =
1993 121 my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
1994 121 str->append(STRING_WITH_LEN("cast("));
1995 121 args[0]->print(thd, str, query_type);
1996 121 str->append(STRING_WITH_LEN(" as decimal("));
1997 121 str->append_ulonglong(precision);
1998 121 str->append(',');
1999 121 str->append_ulonglong(decimals);
2000 121 str->append(')');
2001 121 str->append(')');
2002 121 }
2003
2004 1 String *Item_typecast_real::val_str(String *str) {
2005 1 double res = val_real();
2006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (null_value) return nullptr;
2007
2008 1 str->set_real(res, decimals, collation.collation);
2009 1 return str;
2010 }
2011
2012 125523 double Item_typecast_real::val_real() {
2013 125523 double res = args[0]->val_real();
2014 125523 null_value = args[0]->null_value;
2015
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 125501 times.
125523 if (null_value) return 0.0;
2016
4/4
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 125266 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 125499 times.
125736 if (data_type() == MYSQL_TYPE_FLOAT &&
2017
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 1 times.
235 ((res > std::numeric_limits<float>::max()) ||
2018
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 233 times.
234 res < std::numeric_limits<float>::lowest()))
2019 2 return raise_float_overflow();
2020 125499 return check_float_overflow(res);
2021 }
2022
2023 1 longlong Item_func::val_int_from_real() {
2024 1 double res = val_real();
2025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (null_value) return 0;
2026
2027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (unsigned_flag) {
2028 if (res < 0 || res >= ULLONG_MAX_DOUBLE) {
2029 return raise_integer_overflow();
2030 } else
2031 return (longlong)double2ulonglong(res);
2032 } else {
2033
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (res <= LLONG_MIN || res > LLONG_MAX_DOUBLE) {
2034 1 return raise_integer_overflow();
2035 } else
2036 return (longlong)res;
2037 }
2038 }
2039
2040 1 bool Item_typecast_real::get_date(MYSQL_TIME *ltime,
2041 my_time_flags_t fuzzydate) {
2042 1 return my_double_to_datetime_with_warn(val_real(), ltime, fuzzydate);
2043 }
2044
2045 1 bool Item_typecast_real::get_time(MYSQL_TIME *ltime) {
2046 1 return my_double_to_time_with_warn(val_real(), ltime);
2047 }
2048
2049 2 my_decimal *Item_typecast_real::val_decimal(my_decimal *decimal_value) {
2050 2 double result = val_real();
2051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (null_value) return nullptr;
2052 2 double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
2053
2054 2 return decimal_value;
2055 }
2056
2057 921 void Item_typecast_real::print(const THD *thd, String *str,
2058 enum_query_type query_type) const {
2059 921 str->append(STRING_WITH_LEN("cast("));
2060 921 args[0]->print(thd, str, query_type);
2061 921 str->append(STRING_WITH_LEN(" as "));
2062
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 915 times.
✓ Branch 2 taken 921 times.
✗ Branch 3 not taken.
921 str->append((data_type() == MYSQL_TYPE_FLOAT) ? "float)" : "double)");
2063 921 }
2064
2065 921199 double Item_func_plus::real_op() {
2066 921199 double val1 = args[0]->val_real();
2067
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 921199 times.
921201 if (current_thd->is_error()) return error_real();
2068 921199 double val2 = args[1]->val_real();
2069
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 921196 times.
921200 if (current_thd->is_error()) return error_real();
2070
2071
6/6
✓ Branch 0 taken 921138 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 921104 times.
✓ Branch 4 taken 92 times.
✓ Branch 5 taken 921104 times.
921196 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0.0;
2072 921104 double value = val1 + val2;
2073 921104 return check_float_overflow(value);
2074 }
2075
2076 67766357 longlong Item_func_plus::int_op() {
2077 67766357 longlong val0 = args[0]->val_int();
2078
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 67767102 times.
67767312 if (current_thd->is_error()) return error_int();
2079 67767102 longlong val1 = args[1]->val_int();
2080
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 67767148 times.
67766885 if (current_thd->is_error()) return error_int();
2081 67767148 longlong res = static_cast<unsigned long long>(val0) +
2082 67767148 static_cast<unsigned long long>(val1);
2083 67767148 bool res_unsigned = false;
2084
2085
6/6
✓ Branch 0 taken 67759796 times.
✓ Branch 1 taken 7352 times.
✓ Branch 2 taken 479 times.
✓ Branch 3 taken 67759317 times.
✓ Branch 4 taken 7831 times.
✓ Branch 5 taken 67759317 times.
67767148 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0;
2086
2087 /*
2088 First check whether the result can be represented as a
2089 (bool unsigned_flag, longlong value) pair, then check if it is compatible
2090 with this Item's unsigned_flag by calling check_integer_overflow().
2091 */
2092
2/2
✓ Branch 0 taken 484163 times.
✓ Branch 1 taken 67275154 times.
67759317 if (args[0]->unsigned_flag) {
2093
4/4
✓ Branch 0 taken 103114 times.
✓ Branch 1 taken 381049 times.
✓ Branch 2 taken 103113 times.
✓ Branch 3 taken 1 times.
484163 if (args[1]->unsigned_flag || val1 >= 0) {
2094
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 484135 times.
484162 if (test_if_sum_overflows_ull((ulonglong)val0, (ulonglong)val1)) goto err;
2095 484135 res_unsigned = true;
2096 } else {
2097 /* val1 is negative */
2098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ((ulonglong)val0 > (ulonglong)LLONG_MAX) res_unsigned = true;
2099 }
2100 } else {
2101
2/2
✓ Branch 0 taken 25493 times.
✓ Branch 1 taken 67249661 times.
67275154 if (args[1]->unsigned_flag) {
2102
2/2
✓ Branch 0 taken 25491 times.
✓ Branch 1 taken 2 times.
25493 if (val0 >= 0) {
2103
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 25490 times.
25491 if (test_if_sum_overflows_ull((ulonglong)val0, (ulonglong)val1))
2104 1 goto err;
2105 25490 res_unsigned = true;
2106 } else {
2107
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if ((ulonglong)val1 > (ulonglong)LLONG_MAX) res_unsigned = true;
2108 }
2109 } else {
2110
4/4
✓ Branch 0 taken 67217303 times.
✓ Branch 1 taken 32358 times.
✓ Branch 2 taken 67202943 times.
✓ Branch 3 taken 14360 times.
67249661 if (val0 >= 0 && val1 >= 0)
2111 67202943 res_unsigned = true;
2112
6/6
✓ Branch 0 taken 31995 times.
✓ Branch 1 taken 14723 times.
✓ Branch 2 taken 11729 times.
✓ Branch 3 taken 20266 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 11728 times.
46718 else if (val0 < 0 && val1 < 0 && res >= 0)
2113 1 goto err;
2114 }
2115 }
2116 67759288 return check_integer_overflow(res, res_unsigned);
2117
2118 29 err:
2119 29 return raise_integer_overflow();
2120 }
2121
2122 /**
2123 Calculate plus of two decimals.
2124
2125 @param decimal_value Buffer that can be used to store result
2126
2127 @return Value of operation as a decimal
2128 @retval
2129 0 Value was NULL; In this case null_value is set
2130 */
2131
2132 319733 my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value) {
2133 319733 my_decimal value1, *val1;
2134 319745 my_decimal value2, *val2;
2135
1/2
✓ Branch 0 taken 319736 times.
✗ Branch 1 not taken.
319745 val1 = args[0]->val_decimal(&value1);
2136
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 319726 times.
319736 if ((null_value = args[0]->null_value)) return nullptr;
2137
1/2
✓ Branch 0 taken 319727 times.
✗ Branch 1 not taken.
319726 val2 = args[1]->val_decimal(&value2);
2138
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 319706 times.
319727 if ((null_value = args[1]->null_value)) return nullptr;
2139
2140
2/4
✓ Branch 0 taken 319717 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 319714 times.
✗ Branch 3 not taken.
319706 if (check_decimal_overflow(my_decimal_add(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
2141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 319714 times.
319714 decimal_value, val1, val2)) > 3) {
2142 return error_decimal(decimal_value);
2143 }
2144 319714 return decimal_value;
2145 319745 }
2146
2147 /**
2148 Set precision of results for additive operations (+ and -)
2149 */
2150 1863745 void Item_func_additive_op::result_precision() {
2151 1863745 decimals = max(args[0]->decimals, args[1]->decimals);
2152
1/2
✓ Branch 0 taken 1863737 times.
✗ Branch 1 not taken.
1863752 int arg1_int = args[0]->decimal_precision() - args[0]->decimals;
2153
1/2
✓ Branch 0 taken 1863747 times.
✗ Branch 1 not taken.
1863737 int arg2_int = args[1]->decimal_precision() - args[1]->decimals;
2154 1863747 int precision = max(arg1_int, arg2_int) + 1 + decimals;
2155
2156 /* Integer operations keep unsigned_flag if one of arguments is unsigned */
2157
3/4
✓ Branch 0 taken 1863745 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1824652 times.
✓ Branch 3 taken 39093 times.
1863747 if (result_type() == INT_RESULT)
2158 1824652 unsigned_flag = args[0]->unsigned_flag | args[1]->unsigned_flag;
2159 else
2160 39093 unsigned_flag = args[0]->unsigned_flag & args[1]->unsigned_flag;
2161 3727495 max_length = my_decimal_precision_to_length_no_truncation(precision, decimals,
2162 1863745 unsigned_flag);
2163 1863750 }
2164
2165 /**
2166 The following function is here to allow the user to force
2167 subtraction of UNSIGNED BIGINT/DECIMAL to return negative values.
2168 */
2169
2170 892027 bool Item_func_minus::resolve_type(THD *thd) {
2171
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 892025 times.
892027 if (Item_num_op::resolve_type(thd)) return true;
2172
4/4
✓ Branch 0 taken 63332 times.
✓ Branch 1 taken 828693 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 63303 times.
892025 if (unsigned_flag && (thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
2173 29 unsigned_flag = false;
2174 892025 return false;
2175 }
2176
2177 3679 double Item_func_minus::real_op() {
2178 3679 double val1 = args[0]->val_real();
2179
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3678 times.
3679 if (current_thd->is_error()) return error_real();
2180 3678 double val2 = args[1]->val_real();
2181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3678 times.
3678 if (current_thd->is_error()) return error_real();
2182
2183
6/6
✓ Branch 0 taken 3677 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3676 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3676 times.
3678 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0.0;
2184 3676 double value = val1 - val2;
2185 3676 return check_float_overflow(value);
2186 }
2187
2188 2423816 longlong Item_func_minus::int_op() {
2189 2423816 longlong val0 = args[0]->val_int();
2190
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2423814 times.
2423816 if (current_thd->is_error()) return error_int();
2191 2423814 longlong val1 = args[1]->val_int();
2192
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2423812 times.
2423814 if (current_thd->is_error()) return error_int();
2193 2423812 longlong res = static_cast<unsigned long long>(val0) -
2194 2423812 static_cast<unsigned long long>(val1);
2195 2423812 bool res_unsigned = false;
2196
2197
6/6
✓ Branch 0 taken 2423748 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 2423739 times.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 2423739 times.
2423812 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0;
2198
2199 /*
2200 First check whether the result can be represented as a
2201 (bool unsigned_flag, longlong value) pair, then check if it is compatible
2202 with this Item's unsigned_flag by calling check_integer_overflow().
2203 */
2204
2/2
✓ Branch 0 taken 665307 times.
✓ Branch 1 taken 1758432 times.
2423739 if (args[0]->unsigned_flag) {
2205
2/2
✓ Branch 0 taken 1260 times.
✓ Branch 1 taken 664047 times.
665307 if (args[1]->unsigned_flag) {
2206
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1256 times.
1260 if ((ulonglong)val0 < (ulonglong)val1) {
2207
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (res >= 0) goto err;
2208 } else
2209 1256 res_unsigned = true;
2210 } else {
2211
2/2
✓ Branch 0 taken 664045 times.
✓ Branch 1 taken 2 times.
664047 if (val1 >= 0) {
2212
2/2
✓ Branch 0 taken 643869 times.
✓ Branch 1 taken 20176 times.
664045 if ((ulonglong)val0 > (ulonglong)val1) res_unsigned = true;
2213 } else {
2214
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (test_if_sum_overflows_ull((ulonglong)val0, (ulonglong)-val1))
2215 1 goto err;
2216 1 res_unsigned = true;
2217 }
2218 }
2219 } else {
2220
2/2
✓ Branch 0 taken 1023 times.
✓ Branch 1 taken 1757409 times.
1758432 if (args[1]->unsigned_flag) {
2221
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1022 times.
1023 if ((ulonglong)(val0 - LLONG_MIN) < (ulonglong)val1) goto err;
2222 } else {
2223
4/4
✓ Branch 0 taken 1738261 times.
✓ Branch 1 taken 19148 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1738254 times.
1757409 if (val0 >= 0 && val1 < 0)
2224 7 res_unsigned = true;
2225
5/6
✓ Branch 0 taken 19148 times.
✓ Branch 1 taken 1738254 times.
✓ Branch 2 taken 19148 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 19147 times.
1757402 else if (val0 < 0 && val1 > 0 && res >= 0)
2226 1 goto err;
2227 }
2228 }
2229 2423735 return check_integer_overflow(res, res_unsigned);
2230
2231 4 err:
2232 4 return raise_integer_overflow();
2233 }
2234
2235 /**
2236 See Item_func_plus::decimal_op for comments.
2237 */
2238
2239 205992 my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value) {
2240 205992 my_decimal value1, *val1;
2241 205992 my_decimal value2, *val2;
2242
2243
1/2
✓ Branch 0 taken 205992 times.
✗ Branch 1 not taken.
205992 val1 = args[0]->val_decimal(&value1);
2244
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 205804 times.
205992 if ((null_value = args[0]->null_value)) return nullptr;
2245
2246
1/2
✓ Branch 0 taken 205804 times.
✗ Branch 1 not taken.
205804 val2 = args[1]->val_decimal(&value2);
2247
2/2
✓ Branch 0 taken 227 times.
✓ Branch 1 taken 205577 times.
205804 if ((null_value = args[1]->null_value)) return nullptr;
2248
2249
2/4
✓ Branch 0 taken 205577 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 205577 times.
✗ Branch 3 not taken.
205577 if (check_decimal_overflow(my_decimal_sub(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
2250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 205577 times.
205577 decimal_value, val1, val2)) > 3) {
2251 return error_decimal(decimal_value);
2252 }
2253 /*
2254 Allow sign mismatch only if sql_mode includes MODE_NO_UNSIGNED_SUBTRACTION
2255 See Item_func_minus::resolve_type().
2256 */
2257
6/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 205572 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 205574 times.
205577 if (unsigned_flag && decimal_value->sign()) {
2258
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 raise_decimal_overflow();
2259 3 return error_decimal(decimal_value);
2260 }
2261 205574 return decimal_value;
2262 205992 }
2263
2264 3969358 double Item_func_mul::real_op() {
2265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3969358 times.
3969358 assert(fixed == 1);
2266 3969358 double val1 = args[0]->val_real();
2267
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3969358 times.
3969359 if (current_thd->is_error()) return error_real();
2268 3969358 double val2 = args[1]->val_real();
2269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3969359 times.
3969359 if (current_thd->is_error()) return error_real();
2270
2271
6/6
✓ Branch 0 taken 3969358 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3969357 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3969357 times.
3969359 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0.0;
2272 3969357 double value = val1 * val2;
2273 3969357 return check_float_overflow(value);
2274 }
2275
2276 5938460 longlong Item_func_mul::int_op() {
2277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5938460 times.
5938460 assert(fixed == 1);
2278 5938460 longlong a = args[0]->val_int();
2279
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5938475 times.
5938481 if (current_thd->is_error()) return error_int();
2280 5938475 longlong b = args[1]->val_int();
2281
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5938471 times.
5938478 if (current_thd->is_error()) return error_int();
2282 longlong res;
2283 ulonglong res0, res1;
2284
2285
6/6
✓ Branch 0 taken 5938338 times.
✓ Branch 1 taken 133 times.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 5938259 times.
✓ Branch 4 taken 212 times.
✓ Branch 5 taken 5938259 times.
5938471 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0;
2286
2287
4/4
✓ Branch 0 taken 5821763 times.
✓ Branch 1 taken 116496 times.
✓ Branch 2 taken 448224 times.
✓ Branch 3 taken 5373539 times.
5938259 if (a == 0 || b == 0) return 0;
2288
2289 /*
2290 First check whether the result can be represented as a
2291 (bool unsigned_flag, longlong value) pair, then check if it is compatible
2292 with this Item's unsigned_flag by calling check_integer_overflow().
2293
2294 Let a = a1 * 2^32 + a0 and b = b1 * 2^32 + b0. Then
2295 a * b = (a1 * 2^32 + a0) * (b1 * 2^32 + b0) = a1 * b1 * 2^64 +
2296 + (a1 * b0 + a0 * b1) * 2^32 + a0 * b0;
2297 We can determine if the above sum overflows the ulonglong range by
2298 sequentially checking the following conditions:
2299 1. If both a1 and b1 are non-zero.
2300 2. Otherwise, if (a1 * b0 + a0 * b1) is greater than ULONG_MAX.
2301 3. Otherwise, if (a1 * b0 + a0 * b1) * 2^32 + a0 * b0 is greater than
2302 ULLONG_MAX.
2303
2304 Since we also have to take the unsigned_flag for a and b into account,
2305 it is easier to first work with absolute values and set the
2306 correct sign later.
2307
2308 We handle INT_MIN64 == -9223372036854775808 specially first,
2309 to avoid UBSAN warnings.
2310 */
2311
4/4
✓ Branch 0 taken 5073155 times.
✓ Branch 1 taken 300384 times.
✓ Branch 2 taken 851 times.
✓ Branch 3 taken 5072304 times.
5373539 const bool a_negative = (!args[0]->unsigned_flag && a < 0);
2312
4/4
✓ Branch 0 taken 5363995 times.
✓ Branch 1 taken 9544 times.
✓ Branch 2 taken 652 times.
✓ Branch 3 taken 5363343 times.
5373539 const bool b_negative = (!args[1]->unsigned_flag && b < 0);
2313
2314 5373539 const bool res_unsigned = (a_negative == b_negative);
2315
2316
4/4
✓ Branch 0 taken 851 times.
✓ Branch 1 taken 5372688 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 847 times.
5373539 if (a_negative && a == INT_MIN64) {
2317
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (b == 1) return check_integer_overflow(a, res_unsigned);
2318 3 return raise_integer_overflow();
2319 }
2320
2321
4/4
✓ Branch 0 taken 651 times.
✓ Branch 1 taken 5372884 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 647 times.
5373535 if (b_negative && b == INT_MIN64) {
2322
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (a == 1) return check_integer_overflow(b, res_unsigned);
2323 3 return raise_integer_overflow();
2324 }
2325
2326
2/2
✓ Branch 0 taken 846 times.
✓ Branch 1 taken 5372685 times.
5373531 if (a_negative) {
2327 846 a = -a;
2328 }
2329
2/2
✓ Branch 0 taken 647 times.
✓ Branch 1 taken 5372884 times.
5373531 if (b_negative) {
2330 647 b = -b;
2331 }
2332
2333 5373531 ulong a0 = 0xFFFFFFFFUL & a;
2334 5373531 ulong a1 = ((ulonglong)a) >> 32;
2335 5373531 ulong b0 = 0xFFFFFFFFUL & b;
2336 5373531 ulong b1 = ((ulonglong)b) >> 32;
2337
2338
4/4
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 5373374 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 156 times.
5373531 if (a1 && b1) goto err;
2339
2340 5373530 res1 = (ulonglong)a1 * b0 + (ulonglong)a0 * b1;
2341
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5373523 times.
5373530 if (res1 > 0xFFFFFFFFUL) goto err;
2342
2343 5373523 res1 = res1 << 32;
2344 5373523 res0 = (ulonglong)a0 * b0;
2345
2346
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5373503 times.
5373523 if (test_if_sum_overflows_ull(res1, res0)) goto err;
2347 5373503 res = res1 + res0;
2348
2349
2/2
✓ Branch 0 taken 1333 times.
✓ Branch 1 taken 5372170 times.
5373503 if (a_negative != b_negative) {
2350
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 1248 times.
1333 if ((ulonglong)res > (ulonglong)LLONG_MAX) goto err;
2351 1248 res = -res;
2352 }
2353
2354 5373418 return check_integer_overflow(res, res_unsigned);
2355
2356 94 err:
2357 94 return raise_integer_overflow();
2358 }
2359
2360 /** See Item_func_plus::decimal_op for comments. */
2361
2362 385735 my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value) {
2363 385735 my_decimal value1, *val1;
2364 385735 my_decimal value2, *val2;
2365
1/2
✓ Branch 0 taken 385735 times.
✗ Branch 1 not taken.
385735 val1 = args[0]->val_decimal(&value1);
2366
2/2
✓ Branch 0 taken 253 times.
✓ Branch 1 taken 385482 times.
385735 if ((null_value = args[0]->null_value)) return nullptr;
2367
1/2
✓ Branch 0 taken 385482 times.
✗ Branch 1 not taken.
385482 val2 = args[1]->val_decimal(&value2);
2368
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 385359 times.
385482 if ((null_value = args[1]->null_value)) return nullptr;
2369
2370
2/4
✓ Branch 0 taken 385359 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 385359 times.
✗ Branch 3 not taken.
385359 if (check_decimal_overflow(my_decimal_mul(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
2371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 385359 times.
385359 decimal_value, val1, val2)) > 3) {
2372 return error_decimal(decimal_value);
2373 }
2374 385359 return decimal_value;
2375 385735 }
2376
2377 187909 void Item_func_mul::result_precision() {
2378 /* Integer operations keep unsigned_flag if one of arguments is unsigned */
2379
2/2
✓ Branch 0 taken 168304 times.
✓ Branch 1 taken 19605 times.
187909 if (result_type() == INT_RESULT)
2380 168304 unsigned_flag = args[0]->unsigned_flag | args[1]->unsigned_flag;
2381 else
2382 19605 unsigned_flag = args[0]->unsigned_flag & args[1]->unsigned_flag;
2383 187909 decimals = min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE);
2384
2/4
✓ Branch 0 taken 187909 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 187909 times.
✗ Branch 3 not taken.
187910 uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
2385 187909 uint precision = min<uint>(est_prec, DECIMAL_MAX_PRECISION);
2386 375818 max_length = my_decimal_precision_to_length_no_truncation(precision, decimals,
2387 187909 unsigned_flag);
2388 187909 }
2389
2390 6502 double Item_func_div_base::real_op() {
2391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6502 times.
6502 assert(fixed);
2392 6502 double val1 = args[0]->val_real();
2393
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6501 times.
6502 if (current_thd->is_error()) return error_real();
2394 6501 double val2 = args[1]->val_real();
2395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6501 times.
6501 if (current_thd->is_error()) return error_real();
2396
2397
5/6
✓ Branch 0 taken 6501 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 6488 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 6488 times.
6501 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0.0;
2398
2/2
✓ Branch 0 taken 5043 times.
✓ Branch 1 taken 1445 times.
6488 if (val2 == 0.0) {
2399 5043 signal_divide_by_null();
2400 5043 return 0.0;
2401 }
2402 1445 return check_float_overflow(val1 / val2);
2403 }
2404
2405 1114362 my_decimal *Item_func_div_base::decimal_op(my_decimal *decimal_value) {
2406 1114362 my_decimal value1, *val1;
2407 1114362 my_decimal value2, *val2;
2408 int err;
2409
2410
1/2
✓ Branch 0 taken 1114362 times.
✗ Branch 1 not taken.
1114362 val1 = args[0]->val_decimal(&value1);
2411
2/2
✓ Branch 0 taken 5465 times.
✓ Branch 1 taken 1108897 times.
1114362 if ((null_value = args[0]->null_value)) return nullptr;
2412
1/2
✓ Branch 0 taken 1108897 times.
✗ Branch 1 not taken.
1108897 val2 = args[1]->val_decimal(&value2);
2413
2/2
✓ Branch 0 taken 1002 times.
✓ Branch 1 taken 1107895 times.
1108897 if ((null_value = args[1]->null_value)) return nullptr;
2414
2415
1/2
✓ Branch 0 taken 1107895 times.
✗ Branch 1 not taken.
1107895 if ((err = check_decimal_overflow(
2416 my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW & ~E_DEC_DIV_ZERO,
2417
3/4
✓ Branch 0 taken 1107895 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6138 times.
✓ Branch 3 taken 1101757 times.
2215790 decimal_value, val1, val2, m_prec_increment))) > 3) {
2418
2/4
✓ Branch 0 taken 6138 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6138 times.
✗ Branch 3 not taken.
6138 if (err == E_DEC_DIV_ZERO) signal_divide_by_null();
2419 6138 return error_decimal(decimal_value);
2420 }
2421 1101757 return decimal_value;
2422 1114362 }
2423
2424 580230 void Item_func_div::result_precision() {
2425 580230 uint precision = min<uint>(
2426 580230 args[0]->decimal_precision() + args[1]->decimals + m_prec_increment,
2427
1/2
✓ Branch 0 taken 580230 times.
✗ Branch 1 not taken.
580230 DECIMAL_MAX_PRECISION);
2428
2429
3/4
✓ Branch 0 taken 362477 times.
✓ Branch 1 taken 217753 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 362477 times.
580230 if (result_type() == DECIMAL_RESULT) assert(precision > 0);
2430
2431 /* Integer operations keep unsigned_flag if one of arguments is unsigned */
2432
2/2
✓ Branch 0 taken 217753 times.
✓ Branch 1 taken 362477 times.
580230 if (result_type() == INT_RESULT)
2433 217753 unsigned_flag = args[0]->unsigned_flag | args[1]->unsigned_flag;
2434 else
2435 362477 unsigned_flag = args[0]->unsigned_flag & args[1]->unsigned_flag;
2436 580230 decimals = min<uint>(args[0]->decimals + m_prec_increment, DECIMAL_MAX_SCALE);
2437 1160460 max_length = my_decimal_precision_to_length_no_truncation(precision, decimals,
2438 580230 unsigned_flag);
2439 580230 }
2440
2441 36304 void Item_func_div_int::result_precision() {
2442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36304 times.
36304 assert(result_type() == INT_RESULT);
2443
2444 // Integer operations keep unsigned_flag if one of arguments is unsigned
2445 36304 unsigned_flag = args[0]->unsigned_flag | args[1]->unsigned_flag;
2446
2447 36304 uint arg0_decimals = args[0]->decimals;
2448
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 36284 times.
36304 if (arg0_decimals == DECIMAL_NOT_SPECIFIED) arg0_decimals = 0;
2449 36304 uint arg1_decimals = args[1]->decimals;
2450
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 36285 times.
36304 if (arg1_decimals == DECIMAL_NOT_SPECIFIED)
2451 19 arg1_decimals = args[1]->decimal_precision();
2452
2453 uint precision =
2454 36304 min<uint>(args[0]->decimal_precision() - arg0_decimals + arg1_decimals,
2455
1/2
✓ Branch 0 taken 36304 times.
✗ Branch 1 not taken.
36304 MY_INT64_NUM_DECIMAL_DIGITS);
2456
2457 36304 max_length =
2458 36304 my_decimal_precision_to_length_no_truncation(precision, 0, unsigned_flag);
2459 36304 }
2460
2461 295488 bool Item_func_div::resolve_type(THD *thd) {
2462
1/2
✓ Branch 0 taken 295488 times.
✗ Branch 1 not taken.
295488 DBUG_TRACE;
2463 295488 m_prec_increment = thd->variables.div_precincrement;
2464
3/4
✓ Branch 0 taken 295488 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 295485 times.
295488 if (Item_num_op::resolve_type(thd)) return true;
2465
2466
3/4
✓ Branch 0 taken 5370 times.
✓ Branch 1 taken 217753 times.
✓ Branch 2 taken 72362 times.
✗ Branch 3 not taken.
295485 switch (hybrid_type) {
2467 5370 case REAL_RESULT: {
2468 5370 decimals = max(args[0]->decimals, args[1]->decimals) + m_prec_increment;
2469 5370 decimals = min(decimals, uint8(DECIMAL_NOT_SPECIFIED));
2470 5370 uint tmp = float_length(decimals);
2471
2/2
✓ Branch 0 taken 5306 times.
✓ Branch 1 taken 64 times.
5370 if (decimals == DECIMAL_NOT_SPECIFIED)
2472 5306 max_length = tmp;
2473 else {
2474 64 max_length = args[0]->max_length - args[0]->decimals + decimals;
2475 64 max_length = min(max_length, tmp);
2476 }
2477 5370 break;
2478 }
2479 217753 case INT_RESULT:
2480 217753 set_data_type(MYSQL_TYPE_NEWDECIMAL);
2481 217753 hybrid_type = DECIMAL_RESULT;
2482
3/8
✓ Branch 0 taken 217753 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 217753 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 217753 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
217753 DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
2483
1/2
✓ Branch 0 taken 217753 times.
✗ Branch 1 not taken.
217753 result_precision();
2484 217753 break;
2485 72362 case DECIMAL_RESULT:
2486
1/2
✓ Branch 0 taken 72362 times.
✗ Branch 1 not taken.
72362 result_precision();
2487 72362 break;
2488 default:
2489 assert(0);
2490 }
2491 295485 set_nullable(true); // division by zero
2492 295485 return false;
2493 295488 }
2494
2495 124323 longlong Item_func_div_base::int_op() {
2496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124323 times.
124323 assert(fixed);
2497
2498 /*
2499 Perform division using DECIMAL math if either of the operands has a
2500 non-integer type
2501 */
2502
4/4
✓ Branch 0 taken 124268 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 124256 times.
248591 if (args[0]->result_type() != INT_RESULT ||
2503
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 124256 times.
124268 args[1]->result_type() != INT_RESULT) {
2504 67 my_decimal tmp;
2505
1/2
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
67 my_decimal *val0p = args[0]->val_decimal(&tmp);
2506
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 65 times.
67 if ((null_value = args[0]->null_value)) return 0;
2507
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 my_decimal val0 = *val0p;
2508
2509
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 my_decimal *val1p = args[1]->val_decimal(&tmp);
2510
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 56 times.
65 if ((null_value = args[1]->null_value)) return 0;
2511
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 my_decimal val1 = *val1p;
2512
2513 int err;
2514
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 if ((err = my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp, &val0,
2515
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 53 times.
56 &val1, 0)) > 3) {
2516
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (err == E_DEC_DIV_ZERO) signal_divide_by_null();
2517 3 return 0;
2518 }
2519
2520 53 my_decimal truncated;
2521 53 const bool do_truncate = true;
2522
2/4
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 53 times.
53 if (my_decimal_round(E_DEC_FATAL_ERROR, &tmp, 0, do_truncate, &truncated))
2523 assert(false);
2524
2525 longlong res;
2526
3/4
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 49 times.
53 if (my_decimal2int(E_DEC_FATAL_ERROR, &truncated, unsigned_flag, &res) &
2527 E_DEC_OVERFLOW)
2528
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 raise_integer_overflow();
2529 53 return res;
2530 67 }
2531
2532 124256 longlong val0 = args[0]->val_int();
2533 124256 longlong val1 = args[1]->val_int();
2534 bool val0_negative, val1_negative, res_negative;
2535 ulonglong uval0, uval1, res;
2536
6/6
✓ Branch 0 taken 123399 times.
✓ Branch 1 taken 857 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 123398 times.
✓ Branch 4 taken 858 times.
✓ Branch 5 taken 123398 times.
124256 if ((null_value = (args[0]->null_value || args[1]->null_value))) return 0;
2537
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 123394 times.
123398 if (val1 == 0) {
2538 4 signal_divide_by_null();
2539 4 return 0;
2540 }
2541
2542
4/4
✓ Branch 0 taken 123308 times.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 11697 times.
✓ Branch 3 taken 111611 times.
123394 val0_negative = !args[0]->unsigned_flag && val0 < 0;
2543
3/4
✓ Branch 0 taken 123394 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 123390 times.
123394 val1_negative = !args[1]->unsigned_flag && val1 < 0;
2544 123394 res_negative = val0_negative != val1_negative;
2545
4/4
✓ Branch 0 taken 11697 times.
✓ Branch 1 taken 111697 times.
✓ Branch 2 taken 11695 times.
✓ Branch 3 taken 2 times.
123394 uval0 = (ulonglong)(val0_negative && val0 != LLONG_MIN ? -val0 : val0);
2546
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 123390 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
123394 uval1 = (ulonglong)(val1_negative && val1 != LLONG_MIN ? -val1 : val1);
2547 123394 res = uval0 / uval1;
2548
2/2
✓ Branch 0 taken 11697 times.
✓ Branch 1 taken 111697 times.
123394 if (res_negative) {
2549
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11696 times.
11697 if (res > (ulonglong)LLONG_MAX) return raise_integer_overflow();
2550 11696 res = (ulonglong)(-(longlong)res);
2551 }
2552 123393 return check_integer_overflow(res, !res_negative);
2553 }
2554
2555 36304 bool Item_func_div_int::resolve_type(THD *thd) {
2556 // Integer division forces result to be integer, so force arguments
2557 // that are parameters to be integer as well.
2558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36304 times.
36304 if (param_type_uses_non_param(thd, MYSQL_TYPE_LONGLONG)) return true;
2559
2560
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 36301 times.
36304 if (Item_func_div_base::resolve_type(thd)) return true;
2561 36301 set_nullable(true); // division by zero
2562
2563 36301 return false;
2564 }
2565
2566 36304 void Item_func_div_int::set_numeric_type() {
2567 36304 set_data_type_longlong();
2568 36304 hybrid_type = INT_RESULT;
2569 36304 result_precision();
2570 36304 }
2571
2572 12840749 longlong Item_func_mod::int_op() {
2573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12840749 times.
12840749 assert(fixed == 1);
2574 12840749 longlong val0 = args[0]->val_int();
2575
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12840751 times.
12840753 if (current_thd->is_error()) return error_int();
2576 12840751 longlong val1 = args[1]->val_int();
2577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12840752 times.
12840752 if (current_thd->is_error()) return error_int();
2578 bool val0_negative, val1_negative;
2579 ulonglong uval0, uval1;
2580 ulonglong res;
2581
2582
6/6
✓ Branch 0 taken 12833555 times.
✓ Branch 1 taken 7197 times.
✓ Branch 2 taken 6565 times.
✓ Branch 3 taken 12826990 times.
✓ Branch 4 taken 13762 times.
✓ Branch 5 taken 12826990 times.
12840752 if ((null_value = args[0]->null_value || args[1]->null_value))
2583 13762 return 0; /* purecov: inspected */
2584
2/2
✓ Branch 0 taken 3988 times.
✓ Branch 1 taken 12823002 times.
12826990 if (val1 == 0) {
2585 3988 signal_divide_by_null();
2586 3988 return 0;
2587 }
2588
2589 /*
2590 '%' is calculated by integer division internally. Since dividing
2591 LLONG_MIN by -1 generates SIGFPE, we calculate using unsigned values and
2592 then adjust the sign appropriately.
2593 */
2594
4/4
✓ Branch 0 taken 12778151 times.
✓ Branch 1 taken 44851 times.
✓ Branch 2 taken 36667 times.
✓ Branch 3 taken 12741484 times.
12823002 val0_negative = !args[0]->unsigned_flag && val0 < 0;
2595
4/4
✓ Branch 0 taken 12820846 times.
✓ Branch 1 taken 2156 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 12820841 times.
12823002 val1_negative = !args[1]->unsigned_flag && val1 < 0;
2596
4/4
✓ Branch 0 taken 36667 times.
✓ Branch 1 taken 12786335 times.
✓ Branch 2 taken 36664 times.
✓ Branch 3 taken 3 times.
12823002 uval0 = (ulonglong)(val0_negative && val0 != LLONG_MIN ? -val0 : val0);
2597
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 12822997 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
12823002 uval1 = (ulonglong)(val1_negative && val1 != LLONG_MIN ? -val1 : val1);
2598 12823002 res = uval0 % uval1;
2599 MY_COMPILER_DIAGNOSTIC_PUSH()
2600 // Suppress warning C4146 unary minus operator applied to unsigned type,
2601 // result still unsigned
2602 MY_COMPILER_MSVC_DIAGNOSTIC_IGNORE(4146)
2603
2/2
✓ Branch 0 taken 36667 times.
✓ Branch 1 taken 12786335 times.
12823002 return check_integer_overflow(val0_negative ? -res : res, !val0_negative);
2604 MY_COMPILER_DIAGNOSTIC_POP()
2605 }
2606
2607 100245 double Item_func_mod::real_op() {
2608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100245 times.
100245 assert(fixed == 1);
2609 100245 double val1 = args[0]->val_real();
2610
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 100244 times.
100245 if (current_thd->is_error()) return error_real();
2611 100244 double val2 = args[1]->val_real();
2612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100244 times.
100244 if (current_thd->is_error()) return error_real();
2613
2614
6/6
✓ Branch 0 taken 100224 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 100215 times.
✓ Branch 4 taken 29 times.
✓ Branch 5 taken 100215 times.
100244 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0.0;
2615
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 100211 times.
100215 if (val2 == 0.0) {
2616 4 signal_divide_by_null();
2617 4 return 0.0;
2618 }
2619 100211 return fmod(val1, val2);
2620 }
2621
2622 78 my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value) {
2623 78 my_decimal value1, *val1;
2624 78 my_decimal value2, *val2;
2625
2626
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 val1 = args[0]->val_decimal(&value1);
2627
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 74 times.
78 if ((null_value = args[0]->null_value)) return nullptr;
2628
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 val2 = args[1]->val_decimal(&value2);
2629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if ((null_value = args[1]->null_value)) return nullptr;
2630
3/5
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
74 switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
2631 val1, val2)) {
2632 65 case E_DEC_TRUNCATED:
2633 case E_DEC_OK:
2634 65 return decimal_value;
2635 9 case E_DEC_DIV_ZERO:
2636
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 signal_divide_by_null();
2637 [[fallthrough]];
2638 9 default:
2639 9 null_value = true;
2640 9 return nullptr;
2641 }
2642 78 }
2643
2644 82350 void Item_func_mod::result_precision() {
2645 82350 decimals = max(args[0]->decimals, args[1]->decimals);
2646 uint precision =
2647
1/2
✓ Branch 0 taken 82350 times.
✗ Branch 1 not taken.
82350 max(args[0]->decimal_precision(), args[1]->decimal_precision());
2648
2649 164700 max_length = my_decimal_precision_to_length_no_truncation(precision, decimals,
2650 82350 unsigned_flag);
2651
2652 // Increase max_length if we have: signed % unsigned(precision == scale)
2653
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 81845 times.
81848 if (!args[0]->unsigned_flag && args[1]->unsigned_flag &&
2654
5/6
✓ Branch 0 taken 81848 times.
✓ Branch 1 taken 502 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 82350 times.
164200 args[0]->max_length <= args[1]->max_length &&
2655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 args[1]->decimals == args[1]->decimal_precision()) {
2656 max_length += 1;
2657 }
2658 82350 }
2659
2660 90544 bool Item_func_mod::resolve_type(THD *thd) {
2661
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 90541 times.
90544 if (Item_num_op::resolve_type(thd)) return true;
2662 90541 set_nullable(true);
2663 90541 unsigned_flag = args[0]->unsigned_flag;
2664 90541 return false;
2665 }
2666
2667 4130 double Item_func_neg::real_op() {
2668 4130 double value = args[0]->val_real();
2669 4130 null_value = args[0]->null_value;
2670 4130 return -value;
2671 }
2672
2673 439140 longlong Item_func_neg::int_op() {
2674 439140 longlong value = args[0]->val_int();
2675
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 439120 times.
439141 if ((null_value = args[0]->null_value)) return 0;
2676
4/4
✓ Branch 0 taken 779 times.
✓ Branch 1 taken 438341 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 778 times.
439120 if (args[0]->unsigned_flag && (ulonglong)value > (ulonglong)LLONG_MAX + 1ULL)
2677 1 return raise_integer_overflow();
2678 // For some platforms we need special handling of LLONG_MIN to
2679 // guarantee overflow.
2680
5/6
✓ Branch 0 taken 780 times.
✓ Branch 1 taken 438339 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 778 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
439119 if (value == LLONG_MIN && !args[0]->unsigned_flag && !unsigned_flag)
2681 2 return raise_integer_overflow();
2682 // Avoid doing '-value' below, it is undefined.
2683
4/6
✓ Branch 0 taken 778 times.
✓ Branch 1 taken 438339 times.
✓ Branch 2 taken 778 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 778 times.
✗ Branch 5 not taken.
439117 if (value == LLONG_MIN && args[0]->unsigned_flag && !unsigned_flag)
2684 778 return LLONG_MIN;
2685
4/4
✓ Branch 0 taken 438338 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 70100 times.
✓ Branch 3 taken 368238 times.
438339 return check_integer_overflow(-value, !args[0]->unsigned_flag && value < 0);
2686 }
2687
2688 5161 my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value) {
2689
1/2
✓ Branch 0 taken 5161 times.
✗ Branch 1 not taken.
5161 my_decimal val, *value = args[0]->val_decimal(&val);
2690
1/2
✓ Branch 0 taken 5161 times.
✗ Branch 1 not taken.
5161 if (!(null_value = args[0]->null_value)) {
2691
1/2
✓ Branch 0 taken 5161 times.
✗ Branch 1 not taken.
5161 my_decimal2decimal(value, decimal_value);
2692
1/2
✓ Branch 0 taken 5161 times.
✗ Branch 1 not taken.
5161 my_decimal_neg(decimal_value);
2693 5161 return decimal_value;
2694 }
2695 return nullptr;
2696 5161 }
2697
2698 177251 void Item_func_neg::fix_num_length_and_dec() {
2699 177251 decimals = args[0]->decimals;
2700
2/2
✓ Branch 0 taken 559 times.
✓ Branch 1 taken 176692 times.
177251 max_length = args[0]->max_length + (args[0]->unsigned_flag ? 1 : 0);
2701 // Booleans have max_length = 1, but need to add the minus sign
2702
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 177246 times.
177251 if (max_length == 1) max_length++;
2703 177251 }
2704
2705 177251 bool Item_func_neg::resolve_type(THD *thd) {
2706
1/2
✓ Branch 0 taken 177251 times.
✗ Branch 1 not taken.
177251 DBUG_TRACE;
2707
3/4
✓ Branch 0 taken 177251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 177250 times.
177251 if (Item_func_num1::resolve_type(thd)) return true;
2708 /*
2709 If this is in integer context keep the context as integer if possible
2710 (This is how multiplication and other integer functions works)
2711 Use val() to get value as arg_type doesn't mean that item is
2712 Item_int or Item_real due to existence of Item_param.
2713 */
2714
7/8
✓ Branch 0 taken 173520 times.
✓ Branch 1 taken 3730 times.
✓ Branch 2 taken 173520 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 112690 times.
✓ Branch 5 taken 60830 times.
✓ Branch 6 taken 112688 times.
✓ Branch 7 taken 64562 times.
289940 if (hybrid_type == INT_RESULT && args[0]->const_item() &&
2715
3/4
✓ Branch 0 taken 112690 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112688 times.
✓ Branch 3 taken 2 times.
112690 args[0]->may_eval_const_item(thd)) {
2716
1/2
✓ Branch 0 taken 112688 times.
✗ Branch 1 not taken.
112688 longlong val = args[0]->val_int();
2717
6/6
✓ Branch 0 taken 572 times.
✓ Branch 1 taken 112116 times.
✓ Branch 2 taken 360 times.
✓ Branch 3 taken 212 times.
✓ Branch 4 taken 218 times.
✓ Branch 5 taken 112470 times.
113048 if ((ulonglong)val >= (ulonglong)LLONG_MIN &&
2718 360 ((ulonglong)val != (ulonglong)LLONG_MIN ||
2719
3/4
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 354 times.
360 args[0]->type() != INT_ITEM)) {
2720 /*
2721 Ensure that result is converted to DECIMAL, as longlong can't hold
2722 the negated number
2723 */
2724 218 unsigned_flag = false;
2725
2/4
✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 218 times.
✗ Branch 3 not taken.
218 set_data_type_decimal(args[0]->decimal_precision(), 0);
2726 218 hybrid_type = DECIMAL_RESULT;
2727
3/8
✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 218 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 218 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
218 DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
2728 }
2729 }
2730 177250 unsigned_flag = false;
2731 177250 return false;
2732 177251 }
2733
2734 202 double Item_func_abs::real_op() {
2735 202 double value = args[0]->val_real();
2736 202 null_value = args[0]->null_value;
2737 202 return fabs(value);
2738 }
2739
2740 849694 longlong Item_func_abs::int_op() {
2741 849694 longlong value = args[0]->val_int();
2742
2/2
✓ Branch 0 taken 1813 times.
✓ Branch 1 taken 847881 times.
849694 if ((null_value = args[0]->null_value)) return 0;
2743
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 847872 times.
847881 if (unsigned_flag) return value;
2744 /* -LLONG_MIN = LLONG_MAX + 1 => outside of signed longlong range */
2745
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 847871 times.
847872 if (value == LLONG_MIN) return raise_integer_overflow();
2746 847871 return (value >= 0) ? value : -value;
2747 }
2748
2749 10 my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value) {
2750
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 my_decimal val, *value = args[0]->val_decimal(&val);
2751
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 if (!(null_value = args[0]->null_value)) {
2752
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_decimal2decimal(value, decimal_value);
2753
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
9 if (decimal_value->sign()) my_decimal_neg(decimal_value);
2754 9 return decimal_value;
2755 }
2756 1 return nullptr;
2757 10 }
2758
2759 9390 bool Item_func_abs::resolve_type(THD *thd) {
2760
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9389 times.
9390 if (Item_func_num1::resolve_type(thd)) return true;
2761 9389 unsigned_flag = args[0]->unsigned_flag;
2762 9389 return false;
2763 }
2764
2765 1123 bool Item_dec_func::resolve_type(THD *thd) {
2766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1123 times.
1123 if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DOUBLE)) return true;
2767 1123 decimals = DECIMAL_NOT_SPECIFIED;
2768 1123 max_length = float_length(decimals);
2769 1123 set_nullable(true);
2770 1123 return reject_geometry_args(arg_count, args, this);
2771 }
2772
2773 /** Gateway to natural LOG function. */
2774 44 double Item_func_ln::val_real() {
2775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 assert(fixed == 1);
2776 44 double value = args[0]->val_real();
2777
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 43 times.
44 if ((null_value = args[0]->null_value)) return 0.0;
2778
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 11 times.
43 if (value <= 0.0) {
2779 32 signal_invalid_argument_for_log();
2780 32 return 0.0;
2781 }
2782 11 return log(value);
2783 }
2784
2785 /**
2786 Extended but so slower LOG function.
2787
2788 We have to check if all values are > zero and first one is not one
2789 as these are the cases then result is not a number.
2790 */
2791 41 double Item_func_log::val_real() {
2792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 assert(fixed == 1);
2793 41 double value = args[0]->val_real();
2794
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 39 times.
41 if ((null_value = args[0]->null_value)) return 0.0;
2795
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 32 times.
39 if (value <= 0.0) {
2796 7 signal_invalid_argument_for_log();
2797 7 return 0.0;
2798 }
2799
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 if (arg_count == 2) {
2800 16 double value2 = args[1]->val_real();
2801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if ((null_value = args[1]->null_value)) return 0.0;
2802
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10 times.
16 if (value2 <= 0.0 || value == 1.0) {
2803 6 signal_invalid_argument_for_log();
2804 6 return 0.0;
2805 }
2806 10 return log(value2) / log(value);
2807 }
2808 16 return log(value);
2809 }
2810
2811 25 double Item_func_log2::val_real() {
2812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 assert(fixed == 1);
2813 25 double value = args[0]->val_real();
2814
2815
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
25 if ((null_value = args[0]->null_value)) return 0.0;
2816
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
23 if (value <= 0.0) {
2817 7 signal_invalid_argument_for_log();
2818 7 return 0.0;
2819 }
2820 16 return std::log2(value);
2821 }
2822
2823 34 double Item_func_log10::val_real() {
2824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 assert(fixed == 1);
2825 34 double value = args[0]->val_real();
2826
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 30 times.
34 if ((null_value = args[0]->null_value)) return 0.0;
2827
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 22 times.
30 if (value <= 0.0) {
2828 8 signal_invalid_argument_for_log();
2829 8 return 0.0;
2830 }
2831 22 return log10(value);
2832 }
2833
2834 47 double Item_func_exp::val_real() {
2835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 assert(fixed == 1);
2836 47 double value = args[0]->val_real();
2837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if ((null_value = args[0]->null_value)) return 0.0; /* purecov: inspected */
2838 47 return check_float_overflow(exp(value));
2839 }
2840
2841 820 double Item_func_sqrt::val_real() {
2842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 820 times.
820 assert(fixed == 1);
2843 820 double value = args[0]->val_real();
2844
6/6
✓ Branch 0 taken 785 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 762 times.
✓ Branch 4 taken 58 times.
✓ Branch 5 taken 762 times.
820 if ((null_value = (args[0]->null_value || value < 0)))
2845 58 return 0.0; /* purecov: inspected */
2846 762 return sqrt(value);
2847 }
2848
2849 7179 double Item_func_pow::val_real() {
2850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7179 times.
7179 assert(fixed == 1);
2851 7179 double value = args[0]->val_real();
2852 7179 double val2 = args[1]->val_real();
2853
3/6
✓ Branch 0 taken 7179 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7179 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7179 times.
7179 if ((null_value = (args[0]->null_value || args[1]->null_value)))
2854 return 0.0; /* purecov: inspected */
2855 7179 const double pow_result = pow(value, val2);
2856 7179 return check_float_overflow(pow_result);
2857 }
2858
2859 // Trigonometric functions
2860
2861 29 double Item_func_acos::val_real() {
2862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 assert(fixed == 1);
2863 /* One can use this to defer SELECT processing. */
2864
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 DEBUG_SYNC(current_thd, "before_acos_function");
2865 29 double value = args[0]->val_real();
2866
6/8
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 24 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 24 times.
29 if ((null_value = (args[0]->null_value || (value < -1.0 || value > 1.0))))
2867 5 return 0.0;
2868 24 return acos(value);
2869 }
2870
2871 24 double Item_func_asin::val_real() {
2872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 assert(fixed == 1);
2873 24 double value = args[0]->val_real();
2874
7/8
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 18 times.
24 if ((null_value = (args[0]->null_value || (value < -1.0 || value > 1.0))))
2875 6 return 0.0;
2876 18 return asin(value);
2877 }
2878
2879 41 double Item_func_atan::val_real() {
2880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 assert(fixed == 1);
2881 41 double value = args[0]->val_real();
2882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if ((null_value = args[0]->null_value)) return 0.0;
2883
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 20 times.
41 if (arg_count == 2) {
2884 21 double val2 = args[1]->val_real();
2885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if ((null_value = args[1]->null_value)) return 0.0;
2886 21 return check_float_overflow(atan2(value, val2));
2887 }
2888 20 return atan(value);
2889 }
2890
2891 22 double Item_func_cos::val_real() {
2892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 assert(fixed == 1);
2893 22 double value = args[0]->val_real();
2894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if ((null_value = args[0]->null_value)) return 0.0;
2895 22 return cos(value);
2896 }
2897
2898 94 double Item_func_sin::val_real() {
2899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94 times.
94 assert(fixed == 1);
2900 94 double value = args[0]->val_real();
2901
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 93 times.
94 if ((null_value = args[0]->null_value)) return 0.0;
2902 93 return sin(value);
2903 }
2904
2905 19 double Item_func_tan::val_real() {
2906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 assert(fixed == 1);
2907 19 double value = args[0]->val_real();
2908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((null_value = args[0]->null_value)) return 0.0;
2909 19 return check_float_overflow(tan(value));
2910 }
2911
2912 18 double Item_func_cot::val_real() {
2913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 assert(fixed == 1);
2914 18 double value = args[0]->val_real();
2915
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
18 if ((null_value = args[0]->null_value)) return 0.0;
2916 15 double val2 = tan(value);
2917
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 if (val2 == 0.0) {
2918 10 return raise_float_overflow();
2919 }
2920 5 return check_float_overflow(1.0 / val2);
2921 }
2922
2923 // Bitwise functions
2924
2925 214593 bool Item_func_bit::resolve_type(THD *thd) {
2926 214593 const bool second_arg = binary_result_requires_binary_second_arg();
2927 /*
2928 In ?&?, we assume varbinary; if integer is provided we'll re-prepare.
2929 To force var*binary*, we temporarily change the charset:
2930 */
2931 214593 const CHARSET_INFO *save_cs = thd->variables.collation_connection;
2932 214593 thd->variables.collation_connection = &my_charset_bin;
2933
2/2
✓ Branch 0 taken 70382 times.
✓ Branch 1 taken 144211 times.
214593 if (second_arg) {
2934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70382 times.
70382 if (param_type_uses_non_param(thd)) return true;
2935 } else {
2936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144211 times.
144211 if (param_type_is_default(thd, 0, 1)) return true;
2937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144211 times.
144211 if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true;
2938 }
2939 214593 thd->variables.collation_connection = save_cs;
2940
4/4
✓ Branch 0 taken 70382 times.
✓ Branch 1 taken 144211 times.
✓ Branch 2 taken 588 times.
✓ Branch 3 taken 214005 times.
214593 if (bit_func_returns_binary(args[0], second_arg ? args[1] : nullptr)) {
2941 588 hybrid_type = STRING_RESULT;
2942 588 set_data_type_string(
2943
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 280 times.
1176 max<uint32>(args[0]->max_length, second_arg ? args[1]->max_length : 0U),
2944 &my_charset_bin);
2945 } else {
2946 214005 hybrid_type = INT_RESULT;
2947 214005 set_data_type_longlong();
2948 214005 unsigned_flag = true;
2949 }
2950 214593 return reject_geometry_args(arg_count, args, this);
2951 }
2952
2953 211578 longlong Item_func_bit::val_int() {
2954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 211578 times.
211578 assert(fixed);
2955
2/2
✓ Branch 0 taken 211575 times.
✓ Branch 1 taken 3 times.
211578 if (hybrid_type == INT_RESULT)
2956 211575 return int_op();
2957 else {
2958 String *res;
2959
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (!(res = str_op(&str_value))) return 0;
2960
2961 int ovf_error;
2962 2 const char *from = res->ptr();
2963 2 size_t len = res->length();
2964 2 const char *end = from + len;
2965
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return my_strtoll10(from, &end, &ovf_error);
2966 }
2967 }
2968
2969 28 double Item_func_bit::val_real() {
2970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 assert(fixed);
2971
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 if (hybrid_type == INT_RESULT)
2972 14 return static_cast<ulonglong>(int_op());
2973 else {
2974 String *res;
2975
3/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 12 times.
14 if (!(res = str_op(&str_value))) return 0.0;
2976
2977 int ovf_error;
2978 12 const char *from = res->ptr();
2979 12 size_t len = res->length();
2980 12 const char *end = from + len;
2981
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 return my_strtod(from, &end, &ovf_error);
2982 }
2983 }
2984
2985 32477 my_decimal *Item_func_bit::val_decimal(my_decimal *decimal_value) {
2986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32477 times.
32477 assert(fixed);
2987
2/2
✓ Branch 0 taken 32476 times.
✓ Branch 1 taken 1 times.
32477 if (hybrid_type == INT_RESULT)
2988 32476 return val_decimal_from_int(decimal_value);
2989 else
2990 1 return val_decimal_from_string(decimal_value);
2991 }
2992
2993 2026 String *Item_func_bit::val_str(String *str) {
2994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2026 times.
2026 assert(fixed);
2995
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 1959 times.
2026 if (hybrid_type == INT_RESULT) {
2996 67 longlong nr = int_op();
2997
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66 times.
67 if (null_value) return nullptr;
2998 66 str->set_int(nr, unsigned_flag, collation.collation);
2999 66 return str;
3000 } else
3001 1959 return str_op(str);
3002 }
3003
3004 // Shift-functions, same as << and >> in C/C++
3005
3006 /**
3007 Template function that evaluates the bitwise shift operation over integer
3008 arguments.
3009 @tparam to_left True if left-shift, false if right-shift
3010 */
3011 template <bool to_left>
3012 286690 longlong Item_func_shift::eval_int_op() {
3013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 143345 times.
286690 assert(fixed);
3014 286690 ulonglong res = args[0]->val_uint();
3015
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 143335 times.
286690 if (args[0]->null_value) return error_int();
3016
3017 286670 ulonglong shift = args[1]->val_uint();
3018
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 143322 times.
286670 if (args[1]->null_value) return error_int();
3019
3020 286644 null_value = false;
3021
2/2
✓ Branch 0 taken 143307 times.
✓ Branch 1 taken 15 times.
286644 if (shift < sizeof(longlong) * 8)
3022 286614 return to_left ? (res << shift) : (res >> shift);
3023 30 return 0;
3024 }
3025
3026 /// Instantiations of the above
3027 template longlong Item_func_shift::eval_int_op<true>();
3028 template longlong Item_func_shift::eval_int_op<false>();
3029
3030 /**
3031 Template function that evaluates the bitwise shift operation over binary
3032 string arguments.
3033 @tparam to_left True if left-shift, false if right-shift
3034 */
3035 template <bool to_left>
3036 806 String *Item_func_shift::eval_str_op(String *) {
3037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 403 times.
806 assert(fixed);
3038
3039 806 String tmp_str;
3040
1/2
✓ Branch 0 taken 403 times.
✗ Branch 1 not taken.
806 String *arg = args[0]->val_str(&tmp_str);
3041
4/6
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 402 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
806 if (!arg || args[0]->null_value) return error_str();
3042
3043 804 ssize_t arg_length = arg->length();
3044 804 size_t shift =
3045
1/2
✓ Branch 0 taken 402 times.
✗ Branch 1 not taken.
804 min(args[1]->val_uint(), static_cast<ulonglong>(arg_length) * 8);
3046
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 400 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
804 if (args[1]->null_value) return error_str();
3047
3048
2/6
✓ Branch 0 taken 400 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 400 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
800 if (tmp_value.alloc(arg->length())) return error_str();
3049
3050 800 tmp_value.length(arg_length);
3051 800 tmp_value.set_charset(&my_charset_bin);
3052 /*
3053 Example with left-shift-by-21-bits:
3054 |........|........|........|........|
3055 byte i byte i+1 byte i+2 byte i+3
3056 First (leftmost) bit has number 1.
3057 21 = 2*8 + 5.
3058 Bits of number 1-3 of byte 'i' receive bits 22-24 i.e. the last 3 bits of
3059 byte 'i+2'. So, take byte 'i+2', shift it left by 5 bits, that puts the
3060 last 3 bits of byte 'i+2' in bits 1-3, and 0s elsewhere.
3061 Bits of number 4-8 of byte 'i' receive bits 25-39 i.e. the first 5 bits of
3062 byte 'i+3'. So, take byte 'i+3', shift it right by 3 bits, that puts the
3063 first 5 bits of byte 'i+3' in bits 4-8, and 0s elsewhere.
3064 In total, do OR of both results.
3065 */
3066 800 size_t mod = shift % 8;
3067 800 size_t mod_complement = 8 - mod;
3068 800 ssize_t entire_bytes = shift / 8;
3069
3070 800 const unsigned char *from_c = pointer_cast<const unsigned char *>(arg->ptr());
3071 800 unsigned char *to_c = pointer_cast<unsigned char *>(tmp_value.c_ptr_quick());
3072
3073 if (to_left) {
3074 // Bytes of lower index are overwritten by bytes of higher index
3075
2/2
✓ Branch 0 taken 1957 times.
✓ Branch 1 taken 202 times.
4318 for (ssize_t i = 0; i < arg_length; i++)
3076
2/2
✓ Branch 0 taken 1215 times.
✓ Branch 1 taken 742 times.
3914 if (i + entire_bytes + 1 < arg_length)
3077 2430 to_c[i] = (from_c[i + entire_bytes] << mod) |
3078 2430 (from_c[i + entire_bytes + 1] >> mod_complement);
3079
2/2
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 541 times.
1484 else if (i + entire_bytes + 1 == arg_length)
3080 402 to_c[i] = from_c[i + entire_bytes] << mod;
3081 else
3082 1082 to_c[i] = 0;
3083 } else {
3084 // Bytes of higher index are overwritten by bytes of lower index
3085
2/2
✓ Branch 0 taken 1950 times.
✓ Branch 1 taken 198 times.
4296 for (ssize_t i = arg_length - 1; i >= 0; i--)
3086
2/2
✓ Branch 0 taken 1211 times.
✓ Branch 1 taken 739 times.
3900 if (i > entire_bytes)
3087 2422 to_c[i] = (from_c[i - entire_bytes] >> mod) |
3088 2422 (from_c[i - entire_bytes - 1] << mod_complement);
3089
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 543 times.
1478 else if (i == entire_bytes)
3090 392 to_c[i] = from_c[i - entire_bytes] >> mod;
3091 else
3092 1086 to_c[i] = 0;
3093 }
3094
3095 800 null_value = false;
3096 800 return &tmp_value;
3097 806 }
3098
3099 /// Instantiations of the above
3100 template String *Item_func_shift::eval_str_op<true>(String *);
3101 template String *Item_func_shift::eval_str_op<false>(String *);
3102
3103 // Bit negation ('~')
3104
3105 43 longlong Item_func_bit_neg::int_op() {
3106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 assert(fixed);
3107 43 ulonglong res = (ulonglong)args[0]->val_int();
3108
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 36 times.
43 if (args[0]->null_value) return error_int();
3109 36 null_value = false;
3110 36 return ~res;
3111 }
3112
3113 141 String *Item_func_bit_neg::str_op(String *str) {
3114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
141 assert(fixed);
3115 141 String *res = args[0]->val_str(str);
3116
3/4
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 139 times.
141 if (args[0]->null_value || !res) return error_str();
3117
3118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (tmp_value.alloc(res->length())) return error_str();
3119
3120 139 size_t arg_length = res->length();
3121 139 tmp_value.length(arg_length);
3122 139 tmp_value.set_charset(&my_charset_bin);
3123 139 const unsigned char *from_c = pointer_cast<const unsigned char *>(res->ptr());
3124 139 unsigned char *to_c = pointer_cast<unsigned char *>(tmp_value.c_ptr_quick());
3125 139 size_t i = 0;
3126
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 139 times.
259 while (i + sizeof(longlong) <= arg_length) {
3127 120 int8store(&to_c[i], ~(uint8korr(&from_c[i])));
3128 120 i += sizeof(longlong);
3129 }
3130
2/2
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 139 times.
413 while (i < arg_length) {
3131 274 to_c[i] = ~from_c[i];
3132 274 i++;
3133 }
3134
3135 139 null_value = false;
3136 139 return &tmp_value;
3137 }
3138
3139 /**
3140 Template function used to evaluate the bitwise operation over int arguments.
3141
3142 @param int_func The bitwise function.
3143 */
3144 template <class Int_func>
3145 136536 longlong Item_func_bit_two_param::eval_int_op(Int_func int_func) {
3146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68268 times.
136536 assert(fixed);
3147
1/2
✓ Branch 0 taken 68268 times.
✗ Branch 1 not taken.
136536 ulonglong arg0 = args[0]->val_uint();
3148
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 68205 times.
136536 if (args[0]->null_value) return error_int();
3149
1/2
✓ Branch 0 taken 68205 times.
✗ Branch 1 not taken.
136410 ulonglong arg1 = args[1]->val_uint();
3150
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 68164 times.
136410 if (args[1]->null_value) return error_int();
3151 136328 null_value = false;
3152 136328 return (longlong)int_func(arg0, arg1);
3153 }
3154
3155 /// Instantiations of the above
3156 template longlong Item_func_bit_two_param::eval_int_op<std::bit_or<ulonglong>>(
3157 std::bit_or<ulonglong>);
3158 template longlong Item_func_bit_two_param::eval_int_op<std::bit_and<ulonglong>>(
3159 std::bit_and<ulonglong>);
3160 template longlong Item_func_bit_two_param::eval_int_op<std::bit_xor<ulonglong>>(
3161 std::bit_xor<ulonglong>);
3162
3163 /**
3164 Template function that evaluates the bitwise operation over binary arguments.
3165 Checks that both arguments have same length and applies the bitwise operation
3166
3167 @param char_func The Bitwise function used to evaluate unsigned chars.
3168 @param int_func The Bitwise function used to evaluate unsigned long longs.
3169 */
3170 template <class Char_func, class Int_func>
3171 2864 String *Item_func_bit_two_param::eval_str_op(String *, Char_func char_func,
3172 Int_func int_func) {
3173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1432 times.
2864 assert(fixed);
3174 2864 String arg0_buff;
3175
1/2
✓ Branch 0 taken 1432 times.
✗ Branch 1 not taken.
2864 String *s1 = args[0]->val_str(&arg0_buff);
3176
3177
4/6
✓ Branch 0 taken 1306 times.
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1306 times.
✓ Branch 4 taken 126 times.
✗ Branch 5 not taken.
2864 if (args[0]->null_value || !s1) return error_str();
3178
3179 2612 String arg1_buff;
3180
1/2
✓ Branch 0 taken 1306 times.
✗ Branch 1 not taken.
2612 String *s2 = args[1]->val_str(&arg1_buff);
3181
3182
4/6
✓ Branch 0 taken 1011 times.
✓ Branch 1 taken 295 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1011 times.
✓ Branch 4 taken 295 times.
✗ Branch 5 not taken.
2612 if (args[1]->null_value || !s2) return error_str();
3183
3184 2022 size_t arg_length = s1->length();
3185
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 985 times.
2022 if (arg_length != s2->length()) {
3186
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
52 my_error(ER_INVALID_BITWISE_OPERANDS_SIZE, MYF(0), func_name());
3187
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
52 return error_str();
3188 }
3189
3190
2/6
✓ Branch 0 taken 985 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 985 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1970 if (tmp_value.alloc(arg_length)) return error_str();
3191
3192 1970 tmp_value.length(arg_length);
3193 1970 tmp_value.set_charset(&my_charset_bin);
3194
3195 1970 const uchar *s1_c_p = pointer_cast<const uchar *>(s1->ptr());
3196 1970 const uchar *s2_c_p = pointer_cast<const uchar *>(s2->ptr());
3197 1970 char *res = tmp_value.ptr();
3198 1970 size_t i = 0;
3199
2/2
✓ Branch 0 taken 5135 times.
✓ Branch 1 taken 985 times.
12240 while (i + sizeof(longlong) <= arg_length) {
3200 10270 int8store(&res[i], int_func(uint8korr(&s1_c_p[i]), uint8korr(&s2_c_p[i])));
3201 10270 i += sizeof(longlong);
3202 }
3203
2/2
✓ Branch 0 taken 3082 times.
✓ Branch 1 taken 985 times.
8134 while (i < arg_length) {
3204 6164 res[i] = char_func(s1_c_p[i], s2_c_p[i]);
3205 6164 i++;
3206 }
3207
3208 1970 null_value = false;
3209 1970 return &tmp_value;
3210 2864 }
3211
3212 /// Instantiations of the above
3213 template String *
3214 Item_func_bit_two_param::eval_str_op<std::bit_or<char>, std::bit_or<ulonglong>>(
3215 String *, std::bit_or<char>, std::bit_or<ulonglong>);
3216 template String *Item_func_bit_two_param::eval_str_op<
3217 std::bit_and<char>, std::bit_and<ulonglong>>(String *, std::bit_and<char>,
3218 std::bit_and<ulonglong>);
3219 template String *Item_func_bit_two_param::eval_str_op<
3220 std::bit_xor<char>, std::bit_xor<ulonglong>>(String *, std::bit_xor<char>,
3221 std::bit_xor<ulonglong>);
3222
3223 215708 bool Item::bit_func_returns_binary(const Item *a, const Item *b) {
3224 /*
3225 Checks if the bitwise function should return binary data.
3226 The conditions to return true are the following:
3227
3228 1. If there's only one argument(so b is nullptr),
3229 then a must be a [VAR]BINARY Item, different from the hex/bit/NULL literal.
3230
3231 2. If there are two arguments, both should be [VAR]BINARY
3232 and at least one of them should be different from the hex/bit/NULL literal
3233 */
3234 // Check if a is [VAR]BINARY Item
3235
2/2
✓ Branch 0 taken 2635 times.
✓ Branch 1 taken 213073 times.
218343 bool a_is_binary = a->result_type() == STRING_RESULT &&
3236
2/2
✓ Branch 0 taken 2514 times.
✓ Branch 1 taken 121 times.
2635 a->collation.collation == &my_charset_bin;
3237 // Check if b is not null and is [VAR]BINARY Item
3238
4/4
✓ Branch 0 taken 70382 times.
✓ Branch 1 taken 145326 times.
✓ Branch 2 taken 590 times.
✓ Branch 3 taken 69792 times.
216298 bool b_is_binary = b && b->result_type() == STRING_RESULT &&
3239
2/2
✓ Branch 0 taken 581 times.
✓ Branch 1 taken 9 times.
590 b->collation.collation == &my_charset_bin;
3240
3241
6/6
✓ Branch 0 taken 2514 times.
✓ Branch 1 taken 213194 times.
✓ Branch 2 taken 1312 times.
✓ Branch 3 taken 1202 times.
✓ Branch 4 taken 414 times.
✓ Branch 5 taken 898 times.
217324 return a_is_binary && (!b || b_is_binary) &&
3242
6/6
✓ Branch 0 taken 1409 times.
✓ Branch 1 taken 207 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 1367 times.
✓ Branch 4 taken 163 times.
✓ Branch 5 taken 86 times.
1616 ((a->type() != Item::VARBIN_ITEM && a->type() != Item::NULL_ITEM) ||
3243
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 96 times.
163 (b && b->type() != Item::VARBIN_ITEM &&
3244
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 10 times.
215775 b->type() != Item::NULL_ITEM));
3245 }
3246
3247 // Conversion functions
3248
3249 65301 bool Item_func_int_val::resolve_type_inner(THD *) {
3250
1/2
✓ Branch 0 taken 65301 times.
✗ Branch 1 not taken.
65301 DBUG_TRACE;
3251
3/10
✓ Branch 0 taken 65301 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65301 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 65301 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
65301 DBUG_PRINT("info", ("name %s", func_name()));
3252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65301 times.
65301 assert(args[0]->data_type() != MYSQL_TYPE_INVALID);
3253
3254
3/4
✓ Branch 0 taken 65301 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 65297 times.
65301 if (reject_geometry_args(arg_count, args, this)) return true;
3255
3256
4/6
✓ Branch 0 taken 65297 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64620 times.
✓ Branch 3 taken 87 times.
✓ Branch 4 taken 590 times.
✗ Branch 5 not taken.
65297 switch (args[0]->result_type()) {
3257 64620 case STRING_RESULT:
3258 case REAL_RESULT:
3259
1/2
✓ Branch 0 taken 64620 times.
✗ Branch 1 not taken.
64620 set_data_type_double();
3260 64620 hybrid_type = REAL_RESULT;
3261 64620 break;
3262 87 case INT_RESULT:
3263
1/2
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
87 set_data_type_longlong();
3264 87 unsigned_flag = args[0]->unsigned_flag;
3265 87 hybrid_type = INT_RESULT;
3266 87 break;
3267 590 case DECIMAL_RESULT: {
3268 // For historical reasons, CEILING and FLOOR convert DECIMAL inputs into
3269 // BIGINT (granted that they are small enough to fit) while ROUND and
3270 // TRUNCATE don't. As items are not yet evaluated at this point,
3271 // assumptions must be made about when a conversion from DECIMAL_RESULT to
3272 // INT_RESULT can be safely achieved.
3273 //
3274 // During the rounding operation, we account for signedness by always
3275 // assuming that the argument DECIMAL is signed. Additionally, since we
3276 // call set_data_type_decimal with a scale of 0, we must increment the
3277 // precision here, as the rounding operation may cause an increase in
3278 // order of magnitude.
3279
1/2
✓ Branch 0 taken 590 times.
✗ Branch 1 not taken.
590 int precision = args[0]->decimal_precision() - args[0]->decimals;
3280
2/2
✓ Branch 0 taken 572 times.
✓ Branch 1 taken 18 times.
590 if (args[0]->decimals != 0) ++precision;
3281
1/2
✓ Branch 0 taken 590 times.
✗ Branch 1 not taken.
590 set_data_type_decimal(precision, 0);
3282 590 hybrid_type = DECIMAL_RESULT;
3283
3284 // The max_length of the biggest INT_RESULT, BIGINT, is 20 regardless of
3285 // signedness, as a minus sign will be counted as one digit. A DECIMAL of
3286 // length 20 could be bigger than the max BIGINT value, thus requiring a
3287 // length < 20. DECIMAL_LONGLONG_DIGITS value is 22, which is presumably
3288 // the sum of 20 digits, a minus sign and a decimal point; requiring -2
3289 // when considering the conversion.
3290
2/2
✓ Branch 0 taken 538 times.
✓ Branch 1 taken 52 times.
590 if (max_length < (DECIMAL_LONGLONG_DIGITS - 2)) {
3291
1/2
✓ Branch 0 taken 538 times.
✗ Branch 1 not taken.
538 set_data_type_longlong();
3292 538 hybrid_type = INT_RESULT;
3293 }
3294
3295 590 break;
3296 }
3297 default:
3298 assert(0);
3299 }
3300
3/14
✓ Branch 0 taken 65297 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65297 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 65297 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
65297 DBUG_PRINT("info", ("Type: %s", (hybrid_type == REAL_RESULT
3301 ? "REAL_RESULT"
3302 : hybrid_type == DECIMAL_RESULT
3303 ? "DECIMAL_RESULT"
3304 : hybrid_type == INT_RESULT
3305 ? "INT_RESULT"
3306 : "--ILLEGAL!!!--")));
3307
3308 65297 return false;
3309 65301 }
3310
3311 293 longlong Item_func_ceiling::int_op() {
3312 longlong result;
3313
3/5
✓ Branch 0 taken 293 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 280 times.
✗ Branch 4 not taken.
293 switch (args[0]->result_type()) {
3314 13 case INT_RESULT:
3315
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 result = args[0]->val_int();
3316 13 null_value = args[0]->null_value;
3317 13 break;
3318 280 case DECIMAL_RESULT: {
3319 280 my_decimal dec_buf, *dec;
3320
2/4
✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 280 times.
✗ Branch 3 not taken.
280 if ((dec = Item_func_ceiling::decimal_op(&dec_buf)))
3321
1/2
✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
280 my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
3322 else
3323 result = 0;
3324 280 break;
3325 280 }
3326 default:
3327 result = (longlong)Item_func_ceiling::real_op();
3328 };
3329 293 return result;
3330 }
3331
3332 12 double Item_func_ceiling::real_op() {
3333 12 double value = args[0]->val_real();
3334 12 null_value = args[0]->null_value;
3335 12 return ceil(value);
3336 }
3337
3338 286 my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value) {
3339
1/2
✓ Branch 0 taken 286 times.
✗ Branch 1 not taken.
286 my_decimal val, *value = args[0]->val_decimal(&val);
3340
1/2
✓ Branch 0 taken 286 times.
✗ Branch 1 not taken.
286 if (!(null_value =
3341
1/2
✓ Branch 0 taken 286 times.
✗ Branch 1 not taken.
572 (args[0]->null_value ||
3342
2/4
✓ Branch 0 taken 286 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 286 times.
286 my_decimal_ceiling(E_DEC_FATAL_ERROR, value, decimal_value) > 1)))
3343 286 return decimal_value;
3344 return nullptr;
3345 286 }
3346
3347 38483 longlong Item_func_floor::int_op() {
3348 longlong result;
3349
3/5
✓ Branch 0 taken 38483 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 38448 times.
✗ Branch 4 not taken.
38483 switch (args[0]->result_type()) {
3350 35 case INT_RESULT:
3351
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 result = args[0]->val_int();
3352 35 null_value = args[0]->null_value;
3353 35 break;
3354 38448 case DECIMAL_RESULT: {
3355 38448 my_decimal dec_buf, *dec;
3356
2/4
✓ Branch 0 taken 38448 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38448 times.
✗ Branch 3 not taken.
38448 if ((dec = Item_func_floor::decimal_op(&dec_buf)))
3357
1/2
✓ Branch 0 taken 38448 times.
✗ Branch 1 not taken.
38448 my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
3358 else
3359 result = 0;
3360 38448 break;
3361 38448 }
3362 default:
3363 result = (longlong)Item_func_floor::real_op();
3364 };
3365 38483 return result;
3366 }
3367
3368 689271 double Item_func_floor::real_op() {
3369 689271 double value = args[0]->val_real();
3370 689272 null_value = args[0]->null_value;
3371 689272 return floor(value);
3372 }
3373
3374 412676 my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value) {
3375
1/2
✓ Branch 0 taken 412676 times.
✗ Branch 1 not taken.
412676 my_decimal val, *value = args[0]->val_decimal(&val);
3376
1/2
✓ Branch 0 taken 412676 times.
✗ Branch 1 not taken.
412676 if (!(null_value =
3377
1/2
✓ Branch 0 taken 412676 times.
✗ Branch 1 not taken.
825352 (args[0]->null_value ||
3378
2/4
✓ Branch 0 taken 412676 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 412676 times.
412676 my_decimal_floor(E_DEC_FATAL_ERROR, value, decimal_value) > 1)))
3379 412676 return decimal_value;
3380 return nullptr;
3381 412676 }
3382
3383 73606 bool Item_func_round::resolve_type(THD *thd) {
3384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73606 times.
73606 if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_NEWDECIMAL)) return true;
3385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73606 times.
73606 if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true;
3386
3387
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 73604 times.
73606 if (reject_geometry_args(arg_count, args, this)) return true;
3388
3389
3/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 63314 times.
✓ Branch 2 taken 10256 times.
✗ Branch 3 not taken.
73604 switch (args[0]->result_type()) {
3390 34 case INT_RESULT:
3391 34 set_data_type_longlong();
3392 34 unsigned_flag = args[0]->unsigned_flag;
3393 34 hybrid_type = INT_RESULT;
3394 34 break;
3395 63314 case DECIMAL_RESULT: {
3396 /*
3397 If the rounding precision is known at this stage (constant), use it
3398 to adjust the precision and scale of the result to the minimal
3399 values that will accommodate the answer. Otherwise, use the precision
3400 and scale from the first argument.
3401 If wanted scale is less than argument's scale, reduce it accordingly.
3402 When rounding, make sure to accommodate one extra digit in precision
3403 Example: ROUND(99.999, 2). Here, the type of the argument is
3404 DECIMAL(5, 3). The type of the result is DECIMAL(5,2), since the
3405 result of this operation is 100.00.
3406 Also make sure that precision is greater than zero.
3407 */
3408 longlong val1;
3409
5/6
✓ Branch 0 taken 63290 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 63290 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 63290 times.
✓ Branch 5 taken 24 times.
63314 if (args[1]->const_item() && args[1]->may_eval_const_item(thd)) {
3410 63290 val1 = args[1]->val_int();
3411
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 63287 times.
63290 if ((null_value = args[1]->is_null())) {
3412 3 val1 = 0;
3413 }
3414
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 63286 times.
63290 if (args[1]->unsigned_flag) {
3415
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (val1 > DECIMAL_MAX_SCALE || val1 < 0) val1 = DECIMAL_MAX_SCALE;
3416
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 63275 times.
63286 } else if (val1 > DECIMAL_MAX_SCALE) {
3417 11 val1 = DECIMAL_MAX_SCALE;
3418
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 63267 times.
63275 } else if (val1 < -DECIMAL_MAX_SCALE) {
3419 8 val1 = -DECIMAL_MAX_SCALE;
3420 }
3421 } else {
3422 24 val1 = args[0]->decimals;
3423 }
3424
3425 63314 uint8 precision = args[0]->decimal_precision();
3426 63314 uint8 new_scale = args[0]->decimals;
3427
2/2
✓ Branch 0 taken 53842 times.
✓ Branch 1 taken 9472 times.
63314 if (val1 <= 0) {
3428 53842 precision -= new_scale;
3429
2/2
✓ Branch 0 taken 53809 times.
✓ Branch 1 taken 33 times.
53842 if (!truncate) precision += 1;
3430 53842 new_scale = 0;
3431
2/2
✓ Branch 0 taken 4820 times.
✓ Branch 1 taken 4652 times.
9472 } else if (val1 < new_scale) {
3432 4820 precision -= (new_scale - val1);
3433
2/2
✓ Branch 0 taken 4804 times.
✓ Branch 1 taken 16 times.
4820 if (!truncate) precision += 1;
3434 4820 new_scale = val1;
3435 }
3436
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 63312 times.
63314 if (precision == 0) precision = 1;
3437 63314 set_data_type_decimal(precision, new_scale);
3438 63314 hybrid_type = DECIMAL_RESULT;
3439 63314 break;
3440 }
3441 10256 case REAL_RESULT:
3442 case STRING_RESULT:
3443 10256 set_data_type_double();
3444 10256 hybrid_type = REAL_RESULT;
3445 10256 break;
3446 default:
3447 assert(0); /* This result type isn't handled */
3448 }
3449 73604 return false;
3450 }
3451
3452 40849 double my_double_round(double value, longlong dec, bool dec_unsigned,
3453 bool truncate) {
3454
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 40841 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
40849 bool dec_negative = (dec < 0) && !dec_unsigned;
3455 40849 int log_10_size = array_elements(log_10); // 309
3456
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 40841 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 5 times.
40849 if (dec_negative && dec <= -log_10_size) return 0.0;
3457
3458
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 40841 times.
40846 ulonglong abs_dec = dec_negative ? -dec : dec;
3459
3460
2/2
✓ Branch 0 taken 24298 times.
✓ Branch 1 taken 16548 times.
40846 double tmp = (abs_dec < array_elements(log_10) ? log_10[abs_dec]
3461 16548 : pow(10.0, (double)abs_dec));
3462
3463 40846 double value_mul_tmp = value * tmp;
3464
6/6
✓ Branch 0 taken 40841 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 16559 times.
✓ Branch 3 taken 24282 times.
✓ Branch 4 taken 16559 times.
✓ Branch 5 taken 24287 times.
40846 if (!dec_negative && !std::isfinite(value_mul_tmp)) return value;
3465
3466 24287 double value_div_tmp = value / tmp;
3467
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 24223 times.
24287 if (truncate) {
3468
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if (value >= 0.0)
3469
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 63 times.
64 return dec < 0 ? floor(value_div_tmp) * tmp : floor(value_mul_tmp) / tmp;
3470 else
3471 return dec < 0 ? ceil(value_div_tmp) * tmp : ceil(value_mul_tmp) / tmp;
3472 }
3473
3474
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24219 times.
24223 return dec < 0 ? rint(value_div_tmp) * tmp : rint(value_mul_tmp) / tmp;
3475 }
3476
3477 23095 double Item_func_round::real_op() {
3478 23095 const double value = args[0]->val_real();
3479 23095 const longlong decimal_places = args[1]->val_int();
3480
3481
6/6
✓ Branch 0 taken 23094 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 23092 times.
✓ Branch 4 taken 23092 times.
✓ Branch 5 taken 3 times.
23095 if (!(null_value = args[0]->null_value || args[1]->null_value))
3482 46184 return my_double_round(value, decimal_places, args[1]->unsigned_flag,
3483 23092 truncate);
3484
3485 3 return 0.0;
3486 }
3487
3488 /*
3489 Rounds a given value to a power of 10 specified as the 'to' argument.
3490 */
3491 123 static inline ulonglong my_unsigned_round(ulonglong value, ulonglong to,
3492 bool *round_overflow) {
3493 123 ulonglong tmp = value / to * to;
3494
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 55 times.
123 if (value - tmp < (to >> 1)) {
3495 68 return tmp;
3496 } else {
3497
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 46 times.
55 if (test_if_sum_overflows_ull(tmp, to)) {
3498 9 *round_overflow = true;
3499 9 return 0;
3500 }
3501 46 return tmp + to;
3502 }
3503 }
3504
3505 178 longlong Item_func_round::int_op() {
3506 178 longlong value = args[0]->val_int();
3507 178 longlong dec = args[1]->val_int();
3508 178 decimals = 0;
3509 ulonglong abs_dec;
3510
3/6
✓ Branch 0 taken 178 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 178 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 178 times.
178 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0;
3511
4/4
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 158 times.
178 if ((dec >= 0) || args[1]->unsigned_flag)
3512 20 return value; // integer have not digits after point
3513
3514 MY_COMPILER_DIAGNOSTIC_PUSH()
3515 // Suppress warning C4146 unary minus operator applied to unsigned type,
3516 // result still unsigned
3517 MY_COMPILER_MSVC_DIAGNOSTIC_IGNORE(4146)
3518 158 abs_dec = -static_cast<ulonglong>(dec);
3519 MY_COMPILER_DIAGNOSTIC_POP()
3520 longlong tmp;
3521
3522
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 148 times.
158 if (abs_dec >= array_elements(log_10_int)) return 0;
3523
3524 148 tmp = log_10_int[abs_dec];
3525
3526
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 143 times.
148 if (truncate)
3527
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 return (unsigned_flag) ? ((ulonglong)value / tmp) * tmp
3528 5 : (value / tmp) * tmp;
3529
4/4
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 59 times.
143 else if (unsigned_flag || value >= 0) {
3530 84 bool round_overflow = false;
3531 ulonglong rounded_value =
3532 84 my_unsigned_round(static_cast<ulonglong>(value), tmp, &round_overflow);
3533
4/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 14 times.
84 if (!unsigned_flag && rounded_value > LLONG_MAX)
3534
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 return raise_integer_overflow();
3535
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
74 if (round_overflow) return raise_integer_overflow();
3536 65 return rounded_value;
3537 } else {
3538 // We round "towards nearest", so
3539 // -9223372036854775808 should round to
3540 // -9223372036854775810 which underflows, or
3541 // -9223372036854775800 which is OK, or
3542 // -9223372036854776000 which underflows, and so on ...
3543
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 39 times.
59 if (value == LLONG_MIN) {
3544
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 9 times.
20 switch (abs_dec) {
3545 case 0:
3546 return LLONG_MIN;
3547 11 case 1:
3548 case 3:
3549 case 4:
3550 case 5:
3551 case 6:
3552 case 8:
3553 case 9:
3554 case 10:
3555 case 14:
3556 case 19:
3557
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 return raise_integer_overflow();
3558 9 default:
3559 9 return (LLONG_MIN / tmp) * tmp;
3560 }
3561 }
3562 39 bool not_used = false;
3563 ulonglong rounded_value =
3564 39 my_unsigned_round(static_cast<ulonglong>(-value), tmp, &not_used);
3565
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
39 if (rounded_value > LLONG_MAX) return raise_integer_overflow();
3566
3567 29 return -static_cast<longlong>(rounded_value);
3568 }
3569 }
3570
3571 5252 my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value) {
3572
1/2
✓ Branch 0 taken 5252 times.
✗ Branch 1 not taken.
5252 my_decimal val, *value = args[0]->val_decimal(&val);
3573
1/2
✓ Branch 0 taken 5252 times.
✗ Branch 1 not taken.
5252 longlong dec = args[1]->val_int();
3574
4/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 5213 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 35 times.
5252 if (dec >= 0 || args[1]->unsigned_flag)
3575 5217 dec = min<ulonglong>(dec, decimals);
3576
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 29 times.
35 else if (dec < INT_MIN)
3577 6 dec = INT_MIN;
3578
3579
6/6
✓ Branch 0 taken 4901 times.
✓ Branch 1 taken 351 times.
✓ Branch 2 taken 4900 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 4900 times.
✓ Branch 5 taken 352 times.
10152 if (!(null_value = (args[0]->null_value || args[1]->null_value ||
3580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4900 times.
4900 my_decimal_round(E_DEC_FATAL_ERROR, value, (int)dec,
3581
1/2
✓ Branch 0 taken 4900 times.
✗ Branch 1 not taken.
4900 truncate, decimal_value) > 1)))
3582 4900 return decimal_value;
3583 352 return nullptr;
3584 5252 }
3585
3586 81528 bool Item_func_rand::itemize(Parse_context *pc, Item **res) {
3587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81528 times.
81528 if (skip_itemize(res)) return false;
3588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81528 times.
81528 if (super::itemize(pc, res)) return true;
3589 /*
3590 When RAND() is binlogged, the seed is binlogged too. So the
3591 sequence of random numbers is the same on a replication slave as
3592 on the master. However, if several RAND() values are inserted
3593 into a table, the order in which the rows are modified may differ
3594 between master and slave, because the order is undefined. Hence,
3595 the statement is unsafe to log in statement format.
3596 */
3597 81528 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
3598
3599 81528 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_RAND);
3600 81528 return false;
3601 }
3602
3603 4785 void Item_func_rand::seed_random(Item *arg) {
3604 /*
3605 TODO: do not do reinit 'rand' for every execute of PS/SP if
3606 args[0] is a constant.
3607 */
3608 #ifdef WITH_WSREP
3609 uint32 tmp;
3610 4785 THD *thd = current_thd;
3611
2/8
✓ Branch 0 taken 4785 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4785 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4785 if (WSREP(thd)) {
3612 /* This ensures same random value is assigned to replicated transaction. */
3613 if (wsrep_thd_is_applying(thd))
3614 tmp = thd->wsrep_rand;
3615 else
3616 tmp = thd->wsrep_rand = (uint32)arg->val_int();
3617 } else {
3618 4785 tmp = (uint32)arg->val_int();
3619 }
3620 #else
3621 uint32 tmp = (uint32)arg->val_int();
3622 #endif /* WITH_WSREP */
3623 4785 randominit(m_rand, (uint32)(tmp * 0x10001L + 55555555L),
3624 (uint32)(tmp * 0x10000001L));
3625 4785 }
3626
3627 80949 bool Item_func_rand::resolve_type(THD *thd) {
3628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80950 times.
80949 if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DOUBLE)) return true;
3629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80949 times.
80950 if (Item_real_func::resolve_type(thd)) return true;
3630 80949 return reject_geometry_args(arg_count, args, this);
3631 }
3632
3633 80949 bool Item_func_rand::fix_fields(THD *thd, Item **ref) {
3634
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 80949 times.
80949 if (Item_real_func::fix_fields(thd, ref)) return true;
3635
3636
2/2
✓ Branch 0 taken 4786 times.
✓ Branch 1 taken 76163 times.
80949 if (arg_count > 0) { // Only use argument once in query
3637 /*
3638 Allocate rand structure once: we must use thd->stmt_arena
3639 to create rand in proper mem_root if it's a prepared statement or
3640 stored procedure.
3641
3642 No need to send a Rand log event if seed was given eg: RAND(seed),
3643 as it will be replicated in the query as such.
3644 */
3645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4786 times.
4786 assert(m_rand == nullptr);
3646 4786 m_rand = pointer_cast<rand_struct *>(thd->alloc(sizeof(*m_rand)));
3647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4786 times.
4786 if (m_rand == nullptr) return true;
3648 } else {
3649 /*
3650 Save the seed only the first time RAND() is used in the query
3651 Once events are forwarded rather than recreated,
3652 the following can be skipped if inside the slave thread
3653 */
3654
2/2
✓ Branch 0 taken 69543 times.
✓ Branch 1 taken 6620 times.
76163 if (!thd->rand_used) {
3655 69543 thd->rand_used = true;
3656 69543 thd->rand_saved_seed1 = thd->rand.seed1;
3657 69543 thd->rand_saved_seed2 = thd->rand.seed2;
3658 }
3659 }
3660 80949 return false;
3661 }
3662
3663 4546849 double Item_func_rand::val_real() {
3664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4546849 times.
4546849 assert(fixed);
3665 rand_struct *rand;
3666
2/2
✓ Branch 0 taken 495962 times.
✓ Branch 1 taken 4050887 times.
4546849 if (arg_count > 0) {
3667
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 495946 times.
495962 if (!args[0]->const_for_execution())
3668 16 seed_random(args[0]);
3669
2/2
✓ Branch 0 taken 4769 times.
✓ Branch 1 taken 491177 times.
495946 else if (first_eval) {
3670 /*
3671 Constantness of args[0] may be set during JOIN::optimize(), if arg[0]
3672 is a field item of "constant" table. Thus, we have to evaluate
3673 seed_random() for constant arg there but not at the fix_fields method.
3674 */
3675 4769 first_eval = false;
3676 4769 seed_random(args[0]);
3677 }
3678 495962 rand = m_rand;
3679 } else {
3680 /*
3681 Save the seed only the first time RAND() is used in the query
3682 Once events are forwarded rather than recreated,
3683 the following can be skipped if inside the slave thread
3684 */
3685 4050887 THD *const thd = current_thd;
3686
2/2
✓ Branch 0 taken 89312 times.
✓ Branch 1 taken 3961700 times.
4051012 if (!thd->rand_used) {
3687 89312 thd->rand_used = true;
3688 89312 thd->rand_saved_seed1 = thd->rand.seed1;
3689 89312 thd->rand_saved_seed2 = thd->rand.seed2;
3690 }
3691 4051012 rand = &thd->rand;
3692 }
3693 4546974 return my_rnd(rand);
3694 }
3695
3696 27 bool Item_func_sign::resolve_type(THD *thd) {
3697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DOUBLE)) return true;
3698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (Item_int_func::resolve_type(thd)) return true;
3699 27 return reject_geometry_args(arg_count, args, this);
3700 }
3701
3702 34 longlong Item_func_sign::val_int() {
3703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 assert(fixed == 1);
3704 34 double value = args[0]->val_real();
3705 34 null_value = args[0]->null_value;
3706
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 6 times.
34 return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
3707 }
3708
3709 40 bool Item_func_units::resolve_type(THD *thd) {
3710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DOUBLE)) return true;
3711 40 decimals = DECIMAL_NOT_SPECIFIED;
3712 40 max_length = float_length(decimals);
3713 40 return reject_geometry_args(arg_count, args, this);
3714 }
3715
3716 37 double Item_func_units::val_real() {
3717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 assert(fixed == 1);
3718 37 double value = args[0]->val_real();
3719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if ((null_value = args[0]->null_value)) return 0;
3720 37 return check_float_overflow(value * mul + add);
3721 }
3722
3723 3777 bool Item_func_min_max::resolve_type(THD *thd) {
3724 // If no arguments have type, type of this operator cannot be determined yet
3725
5/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3771 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 3771 times.
3783 if (args[0]->data_type() == MYSQL_TYPE_INVALID &&
3726 6 args[1]->data_type() == MYSQL_TYPE_INVALID)
3727 6 return false;
3728
3729
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3770 times.
3771 if (resolve_type_inner(thd)) return true;
3730 3770 return reject_geometry_args(arg_count, args, this);
3731 }
3732
3733 3777 bool Item_func_min_max::resolve_type_inner(THD *thd) {
3734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3777 times.
3777 if (param_type_uses_non_param(thd)) return true;
3735 3777 aggregate_type(make_array(args, arg_count));
3736 3777 hybrid_type = Field::result_merge_type(data_type());
3737
2/2
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 3546 times.
3777 if (hybrid_type == STRING_RESULT) {
3738 /*
3739 If one or more of the arguments have a temporal data type, temporal_item
3740 must be set for correct conversion from temporal values to various result
3741 types.
3742 */
3743
2/2
✓ Branch 0 taken 508 times.
✓ Branch 1 taken 231 times.
739 for (uint i = 0; i < arg_count; i++) {
3744
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 267 times.
508 if (args[i]->is_temporal()) {
3745 /*
3746 If one of the arguments is DATETIME, overwrite any existing
3747 temporal_item since DATETIME contains both date and time and is the
3748 most general and detailed data type to which other temporal types can
3749 be converted without loss of information.
3750 */
3751
6/6
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 194 times.
✓ Branch 5 taken 47 times.
241 if (!temporal_item || args[i]->data_type() == MYSQL_TYPE_DATETIME)
3752 194 temporal_item = args[i];
3753 }
3754 }
3755 /*
3756 If one or more, but not all, of the arguments have a temporal data type,
3757 the data type of this item must be set temporarily to ensure that the
3758 various aggregate functions derive the correct properties.
3759 */
3760
2/2
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 63 times.
397 enum_field_types tmp_data_type = (!is_temporal() && has_temporal_arg())
3761
2/2
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 65 times.
334 ? temporal_item->data_type()
3762 128 : data_type();
3763 231 enum_field_types aggregated_data_type = data_type();
3764 231 set_data_type(tmp_data_type);
3765
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 230 times.
231 if (aggregate_string_properties(func_name(), args, arg_count)) return true;
3766 230 set_data_type(aggregated_data_type);
3767 } else
3768 3546 aggregate_num_type(hybrid_type, args, arg_count);
3769
3770 /*
3771 LEAST and GREATEST convert JSON values to strings before they are
3772 compared, so their JSON nature is lost. Raise a warning to
3773 indicate to the users that the values are not compared using the
3774 JSON comparator, as they might expect. Also update the field type
3775 of the result to reflect that the result is a string.
3776 */
3777 3776 unsupported_json_comparison(arg_count, args,
3778 "comparison of JSON in the "
3779 "LEAST and GREATEST operators");
3780
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3772 times.
3776 if (data_type() == MYSQL_TYPE_JSON) set_data_type(MYSQL_TYPE_VARCHAR);
3781 3776 return false;
3782 }
3783
3784 209 bool Item_func_min_max::cmp_datetimes(longlong *value) {
3785 209 THD *thd = current_thd;
3786 209 longlong res = 0;
3787
2/2
✓ Branch 0 taken 430 times.
✓ Branch 1 taken 192 times.
622 for (uint i = 0; i < arg_count; i++) {
3788 430 Item **arg = args + i;
3789 bool is_null;
3790 longlong tmp =
3791
1/2
✓ Branch 0 taken 430 times.
✗ Branch 1 not taken.
430 get_datetime_value(thd, &arg, nullptr, temporal_item, &is_null);
3792
3793 // Check if we need to stop (because of error or KILL) and stop the loop
3794
3/4
✓ Branch 0 taken 430 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 429 times.
446 if ((null_value = thd->is_error())) return true;
3795
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 413 times.
429 if ((null_value = args[i]->null_value)) return true;
3796
4/4
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 192 times.
✓ Branch 2 taken 89 times.
✓ Branch 3 taken 132 times.
413 if (i == 0 || (tmp < res) == m_is_least_func) res = tmp;
3797 }
3798 192 *value = res;
3799 192 return false;
3800 }
3801
3802 10 bool Item_func_min_max::cmp_times(longlong *value) {
3803 10 longlong res = 0;
3804
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 8 times.
28 for (uint i = 0; i < arg_count; i++) {
3805 20 longlong tmp = args[i]->val_time_temporal();
3806
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if ((null_value = args[i]->null_value)) return true;
3807
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
18 if (i == 0 || (tmp < res) == m_is_least_func) res = tmp;
3808 }
3809 8 *value = res;
3810 8 return false;
3811 }
3812
3813 179 String *Item_func_min_max::str_op(String *str) {
3814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 179 times.
179 assert(fixed);
3815 179 null_value = false;
3816
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 79 times.
179 if (compare_as_dates()) {
3817 100 longlong result = 0;
3818
4/6
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 89 times.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
180 if (cmp_datetimes(&result)) return error_str();
3819
3820 /*
3821 If result is greater than 0, the winning argument was successfully
3822 converted to a time value and should be converted to a string
3823 formatted in accordance with the data type in temporal_item. Otherwise,
3824 the arguments should be compared based on their raw string value.
3825 */
3826
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 9 times.
89 if (result > 0) {
3827 MYSQL_TIME ltime;
3828 80 enum_field_types field_type = temporal_item->data_type();
3829
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 TIME_from_longlong_packed(&ltime, field_type, result);
3830
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 null_value = my_TIME_to_str(&ltime, str, decimals);
3831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (null_value) return nullptr;
3832
3/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 51 times.
80 if (str->needs_conversion(collation.collation)) {
3833 29 uint errors = 0;
3834 29 StringBuffer<STRING_BUFFER_USUAL_SIZE * 2> convert_string(nullptr);
3835 bool copy_failed =
3836
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 convert_string.copy(str->ptr(), str->length(), str->charset(),
3837 collation.collation, &errors);
3838
5/10
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 29 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 29 times.
29 if (copy_failed || errors || str->copy(convert_string))
3839 return error_str();
3840
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 }
3841 80 return str;
3842 }
3843 }
3844
3845 // Find the least/greatest argument based on string value.
3846 88 String *res = nullptr;
3847 88 bool res_in_str = false;
3848
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 73 times.
254 for (uint i = 0; i < arg_count; i++) {
3849 /*
3850 Because val_str() may reallocate the underlying buffer of its String
3851 parameter, it is paramount the passed String argument do not share an
3852 underlying buffer with the currently stored result against which it will
3853 be compared to ensure that String comparison operates on two
3854 non-overlapping buffers.
3855 */
3856
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 96 times.
181 String *val_buf = res_in_str ? &m_string_buf : str;
3857
4/6
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 93 times.
✗ Branch 5 not taken.
181 assert(!res || (res != val_buf && !res->uses_buffer_owned_by(val_buf)));
3858 181 String *val = args[i]->val_str(val_buf);
3859
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 166 times.
181 if ((null_value = args[i]->null_value)) return nullptr;
3860
4/4
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 110 times.
✓ Branch 3 taken 56 times.
253 if (i == 0 ||
3861
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 56 times.
87 (sortcmp(val, res, collation.collation) < 0) == m_is_least_func) {
3862 110 res = val;
3863 110 res_in_str = !res_in_str;
3864 }
3865 }
3866 73 res->set_charset(collation.collation);
3867 73 return res;
3868 }
3869
3870 85 bool Item_func_min_max::date_op(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) {
3871
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 assert(fixed == 1);
3872 85 longlong result = 0;
3873
3/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 80 times.
85 if (cmp_datetimes(&result)) return true;
3874
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 TIME_from_longlong_packed(ltime, data_type(), result);
3875 int warnings;
3876
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 return check_date(*ltime, non_zero_date(*ltime), fuzzydate, &warnings);
3877 }
3878
3879 10 bool Item_func_min_max::time_op(MYSQL_TIME *ltime) {
3880
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 assert(fixed == 1);
3881 10 longlong result = 0;
3882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (compare_as_dates()) {
3883 if (cmp_datetimes(&result)) return true;
3884 TIME_from_longlong_packed(ltime, data_type(), result);
3885 datetime_to_time(ltime);
3886 return false;
3887 }
3888
3889
3/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
10 if (cmp_times(&result)) return true;
3890
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 TIME_from_longlong_time_packed(ltime, result);
3891 8 return false;
3892 }
3893
3894 31 double Item_func_min_max::real_op() {
3895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 assert(fixed == 1);
3896 31 null_value = false;
3897
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 17 times.
31 if (compare_as_dates()) {
3898 14 longlong result = 0;
3899
3/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13 times.
14 if (cmp_datetimes(&result)) return 0;
3900
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 return double_from_datetime_packed(temporal_item->data_type(), result);
3901 }
3902
3903 // Find the least/greatest argument based on double value.
3904 17 double result = 0.0;
3905
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 15 times.
50 for (uint i = 0; i < arg_count; i++) {
3906 35 const double tmp = args[i]->val_real();
3907
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 33 times.
35 if ((null_value = args[i]->null_value)) return 0.0;
3908
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 10 times.
33 if (i == 0 || (tmp < result) == m_is_least_func) result = tmp;
3909 }
3910 15 return result;
3911 }
3912
3913 13627 longlong Item_func_min_max::int_op() {
3914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13627 times.
13627 assert(fixed);
3915 13627 null_value = false;
3916 13627 longlong res = 0;
3917
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 13622 times.
13627 if (compare_as_dates()) {
3918
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (cmp_datetimes(&res)) return 0;
3919
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 return longlong_from_datetime_packed(temporal_item->data_type(), res);
3920 }
3921
3922 // Find the least/greatest argument based on integer value.
3923
2/2
✓ Branch 0 taken 25825 times.
✓ Branch 1 taken 9263 times.
35088 for (uint i = 0; i < arg_count; i++) {
3924
1/2
✓ Branch 0 taken 25825 times.
✗ Branch 1 not taken.
25825 const longlong val = args[i]->val_int();
3925
2/2
✓ Branch 0 taken 4359 times.
✓ Branch 1 taken 21466 times.
25825 if ((null_value = args[i]->null_value)) return 0;
3926 #ifndef NDEBUG
3927 21466 Integer_value arg_val(val, args[i]->unsigned_flag);
3928
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 21450 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
21466 assert(!unsigned_flag || !arg_val.is_negative());
3929 #endif
3930
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 21450 times.
21466 const bool val_is_smaller = unsigned_flag ? static_cast<ulonglong>(val) <
3931 16 static_cast<ulonglong>(res)
3932 21450 : val < res;
3933
4/4
✓ Branch 0 taken 12199 times.
✓ Branch 1 taken 9267 times.
✓ Branch 2 taken 2761 times.
✓ Branch 3 taken 9438 times.
21466 if (i == 0 || val_is_smaller == m_is_least_func) res = val;
3934 }
3935 9263 return res;
3936 }
3937
3938 34 my_decimal *Item_func_min_max::decimal_op(my_decimal *dec) {
3939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 assert(fixed == 1);
3940 34 null_value = false;
3941
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 29 times.
34 if (compare_as_dates()) {
3942 5 longlong result = 0;
3943
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (cmp_datetimes(&result)) return nullptr;
3944
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 return my_decimal_from_datetime_packed(dec, temporal_item->data_type(),
3945 5 result);
3946 }
3947
3948 // Find the least/greatest argument based on decimal value.
3949
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 my_decimal tmp_buf, *res = args[0]->val_decimal(dec);
3950
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 28 times.
91 for (uint i = 0; i < arg_count; i++) {
3951
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
63 my_decimal *tmp = args[i]->val_decimal(res == dec ? &tmp_buf : dec);
3952
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 62 times.
63 if ((null_value = args[i]->null_value)) return nullptr;
3953
7/8
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 46 times.
✓ Branch 7 taken 16 times.
62 if (i == 0 || (my_decimal_cmp(tmp, res) < 0) == m_is_least_func) res = tmp;
3954 }
3955 // Result must me copied from temporary buffer to remain valid after return.
3956
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (res == &tmp_buf) {
3957
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_decimal2decimal(res, dec);
3958 11 res = dec;
3959 }
3960 28 return res;
3961 29 }
3962
3963 37 double Item_func_min_max::val_real() {
3964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 assert(fixed == 1);
3965
6/6
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 19 times.
37 if (has_temporal_arg() && data_type() == MYSQL_TYPE_VARCHAR)
3966 18 return real_op(); // For correct conversion from temporal value to string.
3967 19 return Item_func_numhybrid::val_real();
3968 }
3969
3970 13603 longlong Item_func_min_max::val_int() {
3971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13603 times.
13603 assert(fixed == 1);
3972
5/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 13598 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 13598 times.
13603 if (has_temporal_arg() && data_type() == MYSQL_TYPE_VARCHAR)
3973 5 return int_op(); // For correct conversion from temporal value to int.
3974 13598 return Item_func_numhybrid::val_int();
3975 }
3976
3977 33 my_decimal *Item_func_min_max::val_decimal(my_decimal *dec) {
3978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 assert(fixed == 1);
3979
6/6
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 28 times.
33 if (has_temporal_arg() && data_type() == MYSQL_TYPE_VARCHAR)
3980 5 return decimal_op(
3981 5 dec); // For correct conversion from temporal value to dec
3982 28 return Item_func_numhybrid::val_decimal(dec);
3983 }
3984
3985 13 bool Item_rollup_group_item::get_date(MYSQL_TIME *ltime,
3986 my_time_flags_t fuzzydate) {
3987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 assert(fixed);
3988
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (rollup_null()) {
3989 2 null_value = true;
3990 2 return true;
3991 }
3992 11 return (null_value = args[0]->get_date(ltime, fuzzydate));
3993 }
3994
3995 5 bool Item_rollup_group_item::get_time(MYSQL_TIME *ltime) {
3996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(fixed);
3997
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (rollup_null()) {
3998 1 null_value = true;
3999 1 return true;
4000 }
4001 4 return (null_value = args[0]->get_time(ltime));
4002 }
4003
4004 323 double Item_rollup_group_item::val_real() {
4005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 323 times.
323 assert(fixed);
4006
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 255 times.
323 if (rollup_null()) {
4007 68 null_value = true;
4008 68 return 0.0;
4009 }
4010 255 double res = args[0]->val_real();
4011
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 240 times.
255 if ((null_value = args[0]->null_value)) return 0.0;
4012 240 return res;
4013 }
4014
4015 7328 longlong Item_rollup_group_item::val_int() {
4016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7328 times.
7328 assert(fixed);
4017
2/2
✓ Branch 0 taken 1002 times.
✓ Branch 1 taken 6326 times.
7328 if (rollup_null()) {
4018 1002 null_value = true;
4019 1002 return 0;
4020 }
4021 6326 longlong res = args[0]->val_int();
4022
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 6230 times.
6326 if ((null_value = args[0]->null_value)) return 0;
4023 6230 return res;
4024 }
4025
4026 1151 String *Item_rollup_group_item::val_str(String *str) {
4027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1151 times.
1151 assert(fixed);
4028
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 1006 times.
1151 if (rollup_null()) {
4029 145 null_value = true;
4030 145 return nullptr;
4031 }
4032 1006 String *res = args[0]->val_str(str);
4033
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 968 times.
1006 if ((null_value = args[0]->null_value)) return nullptr;
4034 968 return res;
4035 }
4036
4037 212 my_decimal *Item_rollup_group_item::val_decimal(my_decimal *dec) {
4038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 assert(fixed);
4039
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 207 times.
212 if (rollup_null()) {
4040 5 null_value = true;
4041 5 return nullptr;
4042 }
4043 207 my_decimal *res = args[0]->val_decimal(dec);
4044
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 168 times.
207 if ((null_value = args[0]->null_value)) return nullptr;
4045 168 return res;
4046 }
4047
4048 5 bool Item_rollup_group_item::val_json(Json_wrapper *result) {
4049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(fixed);
4050
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (rollup_null()) {
4051 1 null_value = true;
4052 1 return false;
4053 }
4054 4 bool res = args[0]->val_json(result);
4055 4 null_value = args[0]->null_value;
4056 4 return res;
4057 }
4058
4059 160 void Item_rollup_group_item::print(const THD *thd, String *str,
4060 enum_query_type query_type) const {
4061
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 134 times.
160 if (query_type & QT_HIDE_ROLLUP_FUNCTIONS) {
4062
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 print_args(thd, str, 0, query_type);
4063 26 return;
4064 }
4065
4066
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 str->append(func_name());
4067
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 str->append('(');
4068
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 print_args(thd, str, 0, query_type);
4069
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 str->append(',');
4070 char buf[16];
4071 134 snprintf(buf, sizeof(buf), "%d", m_min_rollup_level);
4072
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 str->append(buf);
4073
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 str->append(')');
4074 }
4075
4076 239 bool Item_rollup_group_item::eq(const Item *item, bool binary_cmp) const {
4077
4/4
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 139 times.
✓ Branch 3 taken 1 times.
379 return Item_func::eq(item, binary_cmp) &&
4078 140 min_rollup_level() == down_cast<const Item_rollup_group_item *>(item)
4079 379 ->min_rollup_level();
4080 }
4081
4082 18106040 longlong Item_func_length::val_int() {
4083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18106040 times.
18106040 assert(fixed == 1);
4084 18106040 String *res = args[0]->val_str(&value);
4085
2/2
✓ Branch 0 taken 15234845 times.
✓ Branch 1 taken 2871195 times.
18106040 if (!res) {
4086 15234845 null_value = true;
4087 15234845 return 0; /* purecov: inspected */
4088 }
4089 2871195 null_value = false;
4090 2871195 return (longlong)res->length();
4091 }
4092
4093 780198 longlong Item_func_char_length::val_int() {
4094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 780198 times.
780198 assert(fixed == 1);
4095 780198 String *res = args[0]->val_str(&value);
4096
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 780115 times.
780198 if (!res) {
4097 83 null_value = true;
4098 83 return 0; /* purecov: inspected */
4099 }
4100 780115 null_value = false;
4101 780115 return (longlong)res->numchars();
4102 }
4103
4104 128 longlong Item_func_coercibility::val_int() {
4105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
128 assert(fixed == 1);
4106 128 null_value = false;
4107 128 return (longlong)args[0]->collation.derivation;
4108 }
4109
4110 408445 bool Item_func_locate::resolve_type(THD *thd) {
4111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408445 times.
408445 if (param_type_is_default(thd, 0, 2)) return true;
4112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408445 times.
408445 if (param_type_is_default(thd, 2, 3, MYSQL_TYPE_LONGLONG)) return true;
4113 408445 max_length = MY_INT32_NUM_DECIMAL_DIGITS;
4114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408445 times.
408445 if (agg_arg_charsets_for_string_result(collation, args, 1)) return true;
4115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 408445 times.
408445 if (simplify_string_args(thd, collation, args + 1, 1)) return true;
4116 408445 return false;
4117 }
4118
4119 732839 longlong Item_func_locate::val_int() {
4120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 732839 times.
732839 assert(fixed);
4121 // Evaluate the string argument first
4122 732839 const CHARSET_INFO *cs = collation.collation;
4123
1/2
✓ Branch 0 taken 732839 times.
✗ Branch 1 not taken.
732839 String *a = eval_string_arg(cs, args[0], &value1);
4124
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 732698 times.
732839 if (a == nullptr) return error_int();
4125
4126 // Evaluate substring argument in same character set as string argument
4127
1/2
✓ Branch 0 taken 732698 times.
✗ Branch 1 not taken.
732698 String *b = eval_string_arg(cs, args[1], &value2);
4128
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 732642 times.
732698 if (b == nullptr) return error_int();
4129
4130 732642 null_value = false;
4131 /* must be longlong to avoid truncation */
4132 732642 longlong start = 0;
4133 732642 longlong start0 = 0;
4134 my_match_t match;
4135
4136
2/2
✓ Branch 0 taken 31325 times.
✓ Branch 1 taken 701317 times.
732642 if (arg_count == 3) {
4137
1/2
✓ Branch 0 taken 31325 times.
✗ Branch 1 not taken.
31325 const longlong tmp = args[2]->val_int();
4138
6/6
✓ Branch 0 taken 31306 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 31244 times.
✓ Branch 4 taken 81 times.
✓ Branch 5 taken 31244 times.
31325 if ((null_value = args[2]->null_value) || tmp <= 0) return 0;
4139 31244 start0 = start = tmp - 1;
4140
4141
2/2
✓ Branch 0 taken 431 times.
✓ Branch 1 taken 30813 times.
31244 if (start > static_cast<longlong>(a->length())) return 0;
4142
4143 /* start is now sufficiently valid to pass to charpos function */
4144
1/2
✓ Branch 0 taken 30813 times.
✗ Branch 1 not taken.
30813 start = a->charpos((int)start);
4145
4146
2/2
✓ Branch 0 taken 728 times.
✓ Branch 1 taken 30085 times.
30813 if (start + b->length() > a->length()) return 0;
4147 }
4148
4149
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 731356 times.
731402 if (!b->length()) // Found empty string at start
4150 46 return start + 1;
4151
4152
3/4
✓ Branch 0 taken 731356 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 317094 times.
✓ Branch 3 taken 414262 times.
1462712 if (!cs->coll->strstr(cs, a->ptr() + start,
4153 731356 static_cast<uint>(a->length() - start), b->ptr(),
4154 b->length(), &match, 1))
4155 317094 return 0;
4156 414262 return static_cast<longlong>(match.mb_len) + start0 + 1;
4157 }
4158
4159 37148 void Item_func_locate::print(const THD *thd, String *str,
4160 enum_query_type query_type) const {
4161 37148 str->append(STRING_WITH_LEN("locate("));
4162 37148 args[1]->print(thd, str, query_type);
4163 37148 str->append(',');
4164 37148 args[0]->print(thd, str, query_type);
4165
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 36167 times.
37148 if (arg_count == 3) {
4166 981 str->append(',');
4167 981 args[2]->print(thd, str, query_type);
4168 }
4169 37148 str->append(')');
4170 37148 }
4171
4172 43 longlong Item_func_validate_password_strength::val_int() {
4173 char buff[STRING_BUFFER_USUAL_SIZE];
4174 43 String value(buff, sizeof(buff), system_charset_info);
4175
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 String *field = args[0]->val_str(&value);
4176
6/6
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 38 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 38 times.
43 if ((null_value = args[0]->null_value) || field->length() == 0) return 0;
4177
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 return (my_calculate_password_strength(field->ptr(), field->length()));
4178 43 }
4179
4180 138 longlong Item_func_field::val_int() {
4181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 assert(fixed);
4182
4183
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 22 times.
138 if (cmp_type == STRING_RESULT) {
4184 116 const CHARSET_INFO *cs = collation.collation;
4185 116 String *field = eval_string_arg(cs, args[0], &value);
4186
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 110 times.
116 if (field == nullptr) return 0;
4187
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 11 times.
218 for (uint i = 1; i < arg_count; i++) {
4188 207 String *tmp_value = eval_string_arg(cs, args[i], &tmp);
4189
6/6
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 103 times.
✓ Branch 4 taken 99 times.
✓ Branch 5 taken 108 times.
207 if (tmp_value != nullptr && !sortcmp(field, tmp_value, cs)) {
4190 99 return i;
4191 }
4192 }
4193
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 16 times.
22 } else if (cmp_type == INT_RESULT) {
4194 6 longlong val = args[0]->val_int();
4195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (args[0]->null_value) return 0;
4196
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 for (uint i = 1; i < arg_count; i++) {
4197
5/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 5 times.
6 if (val == args[i]->val_int() && !args[i]->null_value) {
4198 1 return i;
4199 }
4200 }
4201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 } else if (cmp_type == DECIMAL_RESULT) {
4202 my_decimal dec_arg_buf, *dec_arg, dec_buf,
4203 *dec = args[0]->val_decimal(&dec_buf);
4204 if (args[0]->null_value) return 0;
4205 for (uint i = 1; i < arg_count; i++) {
4206 dec_arg = args[i]->val_decimal(&dec_arg_buf);
4207 if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec)) {
4208 return i;
4209 }
4210 }
4211 } else {
4212 16 double val = args[0]->val_real();
4213
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 11 times.
16 if (args[0]->null_value) return 0;
4214
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6 times.
30 for (uint i = 1; i < arg_count; i++) {
4215
6/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 19 times.
24 if (val == args[i]->val_real() && !args[i]->null_value) {
4216 5 return i;
4217 }
4218 }
4219 }
4220 22 return 0;
4221 }
4222
4223 76 bool Item_func_field::resolve_type(THD *thd) {
4224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (Item_int_func::resolve_type(thd)) return true;
4225 76 set_nullable(false);
4226 76 max_length = 3;
4227 76 cmp_type = args[0]->result_type();
4228
2/2
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 76 times.
339 for (uint i = 1; i < arg_count; i++)
4229 263 cmp_type = item_cmp_type(cmp_type, args[i]->result_type());
4230
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 17 times.
76 if (cmp_type == STRING_RESULT) {
4231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (agg_arg_charsets_for_string_result(collation, args, 1)) return true;
4232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (simplify_string_args(thd, collation, args + 1, arg_count - 1))
4233 return true;
4234 }
4235 76 return false;
4236 }
4237
4238 55243 longlong Item_func_ascii::val_int() {
4239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55243 times.
55243 assert(fixed == 1);
4240 55243 String *res = args[0]->val_str(&value);
4241
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55241 times.
55243 if (!res) {
4242 2 null_value = true;
4243 2 return 0;
4244 }
4245 55241 null_value = false;
4246
2/2
✓ Branch 0 taken 55239 times.
✓ Branch 1 taken 2 times.
55241 return (longlong)(res->length() ? (uchar)(*res)[0] : (uchar)0);
4247 }
4248
4249 656429 longlong Item_func_ord::val_int() {
4250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 656429 times.
656429 assert(fixed == 1);
4251 656429 String *res = args[0]->val_str(&value);
4252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 656429 times.
656429 if (!res) {
4253 null_value = true;
4254 return 0;
4255 }
4256 656429 null_value = false;
4257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 656429 times.
656429 if (!res->length()) return 0;
4258
2/2
✓ Branch 0 taken 611942 times.
✓ Branch 1 taken 44487 times.
656429 if (use_mb(res->charset())) {
4259 611942 const char *str = res->ptr();
4260 611942 uint32 n = 0, l = my_ismbchar(res->charset(), str, str + res->length());
4261
2/2
✓ Branch 0 taken 17046 times.
✓ Branch 1 taken 594896 times.
611942 if (!l) return (longlong)((uchar)*str);
4262
2/2
✓ Branch 0 taken 1251290 times.
✓ Branch 1 taken 594896 times.
1846186 while (l--) n = (n << 8) | (uint32)((uchar)*str++);
4263 594896 return (longlong)n;
4264 }
4265 44487 return (longlong)((uchar)(*res)[0]);
4266 }
4267
4268 /* Search after a string in a string of strings separated by ',' */
4269 /* Returns number of found type >= 1 or 0 if not found */
4270 /* This optimizes searching in enums to bit testing! */
4271
4272 5681 bool Item_func_find_in_set::resolve_type(THD *thd) {
4273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5681 times.
5681 if (param_type_is_default(thd, 0, -1)) return true;
4274 5681 max_length = 3; // 1-999
4275
4276
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5679 times.
5681 if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) {
4277 2 return true;
4278 }
4279
6/6
✓ Branch 0 taken 5403 times.
✓ Branch 1 taken 276 times.
✓ Branch 2 taken 4329 times.
✓ Branch 3 taken 1074 times.
✓ Branch 4 taken 4327 times.
✓ Branch 5 taken 1352 times.
10008 if (args[0]->const_item() && args[1]->type() == FIELD_ITEM &&
4280
2/2
✓ Branch 0 taken 4327 times.
✓ Branch 1 taken 2 times.
4329 args[0]->may_eval_const_item(thd)) {
4281 4327 Field *field = down_cast<Item_field *>(args[1])->field;
4282
2/2
✓ Branch 0 taken 4322 times.
✓ Branch 1 taken 5 times.
4327 if (field->real_type() == MYSQL_TYPE_SET) {
4283 4322 String *find = args[0]->val_str(&value);
4284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4322 times.
4322 if (thd->is_error()) return true;
4285
2/2
✓ Branch 0 taken 4320 times.
✓ Branch 1 taken 2 times.
4322 if (find != nullptr) {
4286 // find is not NULL pointer so args[0] is not a null-value
4287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4320 times.
4320 assert(!args[0]->null_value);
4288 8640 m_enum_value = find_type(down_cast<Field_enum *>(field)->typelib,
4289 4320 find->ptr(), find->length(), false);
4290 }
4291 }
4292 }
4293 5679 return false;
4294 }
4295
4296 static const char separator = ',';
4297
4298 4960 longlong Item_func_find_in_set::val_int() {
4299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4960 times.
4960 assert(fixed);
4300
4301 4960 null_value = false;
4302
4303
2/2
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 4565 times.
4960 if (m_enum_value != 0) {
4304 // enum_value is set iff args[0]->const_item() in resolve_type().
4305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 assert(args[0]->const_item());
4306
4307 395 ulonglong tmp = static_cast<ulonglong>(args[1]->val_int());
4308
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 394 times.
395 if (args[1]->null_value) return error_int();
4309 /*
4310 No need to check args[0]->null_value since enum_value is set iff
4311 args[0] is a non-null const item. Note: no assert on
4312 args[0]->null_value here because args[0] may have been replaced
4313 by an Item_cache on which val_int() has not been called. See
4314 BUG#11766317
4315 */
4316
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 336 times.
394 return (tmp & (1ULL << (m_enum_value - 1))) ? m_enum_value : 0;
4317 }
4318
4319 4565 String *find = args[0]->val_str(&value);
4320
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4545 times.
4565 if (find == nullptr) return error_int();
4321
4322
4/4
✓ Branch 0 taken 551 times.
✓ Branch 1 taken 3994 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 4490 times.
5096 if (args[1]->type() == FIELD_ITEM &&
4323
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 496 times.
551 down_cast<Item_field *>(args[1])->field->real_type() == MYSQL_TYPE_SET) {
4324 55 Field *field = down_cast<Item_field *>(args[1])->field;
4325
4326 55 ulonglong tmp = static_cast<ulonglong>(args[1]->val_int());
4327
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 52 times.
55 if (args[1]->null_value) return error_int();
4328
4329 52 uint value = find_type(down_cast<Field_enum *>(field)->typelib, find->ptr(),
4330 find->length(), false);
4331
4/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 2 times.
52 return (value != 0 && (tmp & (1ULL << (value - 1)))) ? value : 0;
4332 }
4333
4334 4490 String *buffer = args[1]->val_str(&value2);
4335
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4488 times.
4490 if (buffer == nullptr) return error_int();
4336
4337
2/2
✓ Branch 0 taken 4230 times.
✓ Branch 1 taken 258 times.
4488 if (buffer->length() >= find->length()) {
4338 4230 my_wc_t wc = 0;
4339 4230 const CHARSET_INFO *cs = cmp_collation.collation;
4340 4230 const char *str_begin = buffer->ptr();
4341 4230 const char *str_end = buffer->ptr();
4342 4230 const char *real_end = str_end + buffer->length();
4343 4230 const uchar *find_str = (const uchar *)find->ptr();
4344 4230 size_t find_str_len = find->length();
4345 4230 int position = 0;
4346 while (true) {
4347 int symbol_len;
4348 72094 if ((symbol_len =
4349
1/2
✓ Branch 0 taken 72094 times.
✗ Branch 1 not taken.
72094 cs->cset->mb_wc(cs, &wc, pointer_cast<const uchar *>(str_end),
4350
2/2
✓ Branch 0 taken 69181 times.
✓ Branch 1 taken 2913 times.
72094 pointer_cast<const uchar *>(real_end))) > 0) {
4351 69181 const char *substr_end = str_end + symbol_len;
4352 69181 bool is_last_item = (substr_end == real_end);
4353 69181 bool is_separator = (wc == (my_wc_t)separator);
4354
4/4
✓ Branch 0 taken 66641 times.
✓ Branch 1 taken 2540 times.
✓ Branch 2 taken 3611 times.
✓ Branch 3 taken 63030 times.
69181 if (is_separator || is_last_item) {
4355 6151 position++;
4356
4/4
✓ Branch 0 taken 3751 times.
✓ Branch 1 taken 2400 times.
✓ Branch 2 taken 3611 times.
✓ Branch 3 taken 140 times.
6151 if (is_last_item && !is_separator) str_end = substr_end;
4357
3/4
✓ Branch 0 taken 6151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1317 times.
✓ Branch 3 taken 4834 times.
6151 if (!my_strnncoll(cs, (const uchar *)str_begin,
4358 (uint)(str_end - str_begin), find_str,
4359 find_str_len))
4360 1317 return (longlong)position;
4361 else
4362 4834 str_begin = substr_end;
4363 }
4364 67864 str_end = substr_end;
4365
3/4
✓ Branch 0 taken 2913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2016 times.
✓ Branch 3 taken 897 times.
2913 } else if (str_end - str_begin == 0 && find_str_len == 0 &&
4366
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2015 times.
2016 wc == (my_wc_t)separator) {
4367 1 return ++position;
4368 } else {
4369 2912 return 0;
4370 }
4371 67864 }
4372 }
4373 258 return 0;
4374 }
4375
4376 639 longlong Item_func_bit_count::val_int() {
4377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 639 times.
639 assert(fixed);
4378
2/2
✓ Branch 0 taken 558 times.
✓ Branch 1 taken 81 times.
639 if (bit_func_returns_binary(args[0], nullptr)) {
4379 558 String *s = args[0]->val_str(&str_value);
4380
3/4
✓ Branch 0 taken 554 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 554 times.
558 if (args[0]->null_value || !s) return error_int();
4381
4382 554 const char *val = s->ptr();
4383
4384 554 longlong len = 0;
4385 554 size_t i = 0;
4386 554 size_t arg_length = s->length();
4387
2/2
✓ Branch 0 taken 5025 times.
✓ Branch 1 taken 554 times.
5579 while (i + sizeof(longlong) <= arg_length) {
4388 5025 len += my_count_bits(uint8korr(&val[i]));
4389 5025 i += sizeof(longlong);
4390 }
4391
2/2
✓ Branch 0 taken 792 times.
✓ Branch 1 taken 554 times.
1346 while (i < arg_length) {
4392 792 len += _my_bits_nbits[(uchar)val[i]];
4393 792 i++;
4394 }
4395
4396 554 null_value = false;
4397 554 return len;
4398 }
4399
4400 81 ulonglong value = (ulonglong)args[0]->val_int();
4401
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 68 times.
81 if (args[0]->null_value) return error_int(); /* purecov: inspected */
4402
4403 68 null_value = false;
4404 68 return (longlong)my_count_bits(value);
4405 }
4406
4407 /****************************************************************************
4408 ** Functions to handle dynamic loadable functions
4409 ****************************************************************************/
4410
4411 19661 udf_handler::udf_handler(udf_func *udf_arg)
4412 19661 : u_d(udf_arg),
4413 19661 m_args_extension(),
4414 19661 m_return_value_extension(&my_charset_bin, result_type()) {}
4415
4416 19664 void udf_handler::cleanup() {
4417
4/4
✓ Branch 0 taken 19656 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 500 times.
✓ Branch 3 taken 19156 times.
19664 if (!m_original || !m_initialized) return;
4418
4419 19156 clean_buffers();
4420 /*
4421 Make sure to not free the handler from the cleanup() call when
4422 (re)preparing the UDF function call. The handler allocated by
4423 udf_handler::fix_fields() will be used in execution.
4424 */
4425 19156 THD *thd = current_thd;
4426
6/6
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 19072 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 47 times.
✓ Branch 5 taken 19109 times.
19155 if (thd->stmt_arena->is_stmt_prepare() && thd->stmt_arena->is_repreparing)
4427 47 return;
4428
4429
4/4
✓ Branch 0 taken 18739 times.
✓ Branch 1 taken 370 times.
✓ Branch 2 taken 18067 times.
✓ Branch 3 taken 672 times.
19109 if (m_init_func_called && u_d->func_deinit != nullptr) {
4430 18067 (*u_d->func_deinit)(&initid);
4431 18067 m_init_func_called = false;
4432 }
4433
1/2
✓ Branch 0 taken 19109 times.
✗ Branch 1 not taken.
19109 DEBUG_SYNC(current_thd, "udf_handler_destroy_sync");
4434 19109 free_handler();
4435 }
4436
4437 19620 void udf_handler::clean_buffers() {
4438
2/2
✓ Branch 0 taken 9923 times.
✓ Branch 1 taken 9697 times.
19620 if (buffers == nullptr) return;
4439
2/2
✓ Branch 0 taken 25203 times.
✓ Branch 1 taken 9697 times.
34900 for (uint i = 0; i < f_args.arg_count; i++) {
4440 25203 buffers[i].mem_free();
4441 }
4442 }
4443
4444 19574 void udf_handler::free_handler() {
4445 // deinit() should have been called by cleanup()
4446
3/6
✓ Branch 0 taken 19574 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19574 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19574 times.
✗ Branch 5 not taken.
19574 assert(m_original && m_initialized && u_d != nullptr);
4447 19574 free_udf(u_d);
4448 19574 u_d = nullptr;
4449 19574 m_initialized = false;
4450 19574 }
4451
4452 19535 bool Item_udf_func::fix_fields(THD *thd, Item **) {
4453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19535 times.
19535 assert(fixed == 0);
4454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19536 times.
19535 assert(!thd->is_error());
4455
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 19073 times.
19536 if (udf.fix_fields(thd, this, arg_count, args)) return true;
4456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19075 times.
19073 if (thd->is_error()) return true;
4457 19075 used_tables_cache = udf.used_tables_cache;
4458 19075 fixed = true;
4459 19075 return false;
4460 }
4461
4462 19573 bool udf_handler::fix_fields(THD *thd, Item_result_field *func, uint arg_count,
4463 Item **arguments) {
4464 uchar buff[STACK_BUFF_ALLOC]; // Max argument in function
4465
1/2
✓ Branch 0 taken 19574 times.
✗ Branch 1 not taken.
19573 DBUG_TRACE;
4466
4467
2/4
✓ Branch 0 taken 19573 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19573 times.
19574 if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
4468 return true; // Fatal error flag is set!
4469
4470
1/2
✓ Branch 0 taken 19574 times.
✗ Branch 1 not taken.
19573 udf_func *tmp_udf = find_udf(u_d->name.str, (uint)u_d->name.length, true);
4471
4472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19574 times.
19574 if (!tmp_udf) {
4473 my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str);
4474 return true;
4475 }
4476 19574 u_d = tmp_udf;
4477 19574 args = arguments;
4478
4479 19574 m_initialized = true; // Use count was incremented by find_udf()
4480 /*
4481 RAII wrapper to free the memory allocated in case of any failure while
4482 initializing the UDF
4483 */
4484 class cleanup_guard {
4485 public:
4486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19574 times.
19574 cleanup_guard(udf_handler *udf) : m_udf(udf) { assert(udf); }
4487 20038 ~cleanup_guard() {
4488
2/2
✓ Branch 0 taken 19108 times.
✓ Branch 1 taken 465 times.
19573 if (m_udf == nullptr) return;
4489 465 m_udf->clean_buffers();
4490 465 m_udf->free_handler();
4491 19573 }
4492 19107 void defer() { m_udf = nullptr; }
4493
4494 private:
4495 udf_handler *m_udf;
4496 19574 } udf_fun_guard(this);
4497
4498 /* Fix all arguments */
4499 19574 func->set_nullable(false);
4500 19574 used_tables_cache = 0;
4501
4502
2/2
✓ Branch 0 taken 9656 times.
✓ Branch 1 taken 9918 times.
19574 if ((f_args.arg_count = arg_count)) {
4503 9656 if (!(f_args.arg_type =
4504
1/2
✓ Branch 0 taken 9656 times.
✗ Branch 1 not taken.
9656 (Item_result *)(*THR_MALLOC)
4505
2/4
✓ Branch 0 taken 9656 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9656 times.
9656 ->Alloc(f_args.arg_count * sizeof(Item_result)))) {
4506 return true;
4507 }
4508 uint i;
4509 Item **arg, **arg_end;
4510 9656 for (i = 0, arg = arguments, arg_end = arguments + arg_count;
4511
2/2
✓ Branch 0 taken 25105 times.
✓ Branch 1 taken 9653 times.
34758 arg != arg_end; arg++, i++) {
4512
7/8
✓ Branch 0 taken 17733 times.
✓ Branch 1 taken 7372 times.
✓ Branch 2 taken 17733 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 17732 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 25104 times.
25105 if (!(*arg)->fixed && (*arg)->fix_fields(thd, arg)) {
4513 1 return true;
4514 }
4515 // we can't assign 'item' before, because fix_fields() can change arg
4516 25104 Item *item = *arg;
4517
3/4
✓ Branch 0 taken 25104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 25102 times.
25104 if (item->check_cols(1)) {
4518 2 return true;
4519 }
4520 /*
4521 TODO: We should think about this. It is not always
4522 right way just to set an UDF result to return my_charset_bin
4523 if one argument has binary sorting order.
4524 The result collation should be calculated according to arguments
4525 derivations in some cases and should not in other cases.
4526 Moreover, some arguments can represent a numeric input
4527 which doesn't effect the result character set and collation.
4528 There is no a general rule for UDF. Everything depends on
4529 the particular user defined function.
4530 */
4531
2/2
✓ Branch 0 taken 7472 times.
✓ Branch 1 taken 17630 times.
25102 if (item->collation.collation->state & MY_CS_BINSORT)
4532 7472 func->collation.set(&my_charset_bin);
4533 25102 func->m_nullable |= item->m_nullable;
4534 25102 func->add_accum_properties(item);
4535
1/2
✓ Branch 0 taken 25102 times.
✗ Branch 1 not taken.
25102 used_tables_cache |= item->used_tables();
4536
1/2
✓ Branch 0 taken 25102 times.
✗ Branch 1 not taken.
25102 f_args.arg_type[i] = item->result_type();
4537 }
4538 // TODO: why all following memory is not allocated with 1 call of sql_alloc?
4539 // if (!(buffers = new String[arg_count]) ||
4540 9653 if (!(buffers = pointer_cast<String *>(
4541
2/4
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9653 times.
✗ Branch 3 not taken.
9653 (*THR_MALLOC)->Alloc(sizeof(String) * arg_count))) ||
4542 9653 !(f_args.args =
4543
3/6
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9653 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9653 times.
✗ Branch 5 not taken.
9653 (char **)(*THR_MALLOC)->Alloc(arg_count * sizeof(char *))) ||
4544 9653 !(f_args.lengths =
4545
3/6
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9653 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9653 times.
✗ Branch 5 not taken.
9653 (ulong *)(*THR_MALLOC)->Alloc(arg_count * sizeof(long))) ||
4546 9653 !(f_args.maybe_null =
4547
3/6
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9653 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9653 times.
✗ Branch 5 not taken.
9653 (char *)(*THR_MALLOC)->Alloc(arg_count * sizeof(char))) ||
4548
1/2
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
9653 !(num_buffer = (char *)(*THR_MALLOC)
4549
2/4
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9653 times.
✗ Branch 3 not taken.
9653 ->Alloc(arg_count * ALIGN_SIZE(sizeof(double)))) ||
4550 9653 !(f_args.attributes =
4551
3/6
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9653 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9653 times.
✗ Branch 5 not taken.
9653 (char **)(*THR_MALLOC)->Alloc(arg_count * sizeof(char *))) ||
4552 9653 !(f_args.attribute_lengths =
4553
5/10
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9653 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9653 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9653 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 9653 times.
28959 (ulong *)(*THR_MALLOC)->Alloc(arg_count * sizeof(long))) ||
4554 9653 !(m_args_extension.charset_info =
4555
1/2
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
9653 (const CHARSET_INFO **)(*THR_MALLOC)
4556
2/4
✓ Branch 0 taken 9653 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9653 times.
9653 ->Alloc(f_args.arg_count * sizeof(CHARSET_INFO *)))) {
4557 return true;
4558 }
4559 }
4560
2/2
✓ Branch 0 taken 25101 times.
✓ Branch 1 taken 19571 times.
44672 for (uint i = 0; i < arg_count; i++) {
4561 25101 (void)::new (buffers + i) String;
4562 25101 m_args_extension.charset_info[i] = nullptr;
4563 }
4564
4565
2/4
✓ Branch 0 taken 19571 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19571 times.
19571 if (func->resolve_type(thd)) return true;
4566
4567 19571 initid.max_length = func->max_length;
4568 19571 initid.maybe_null = func->m_nullable;
4569 19571 initid.const_item = used_tables_cache == 0;
4570 19571 initid.decimals = func->decimals;
4571 19571 initid.ptr = nullptr;
4572 19571 initid.extension = &m_return_value_extension;
4573
4574
6/6
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 19487 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 31 times.
✓ Branch 5 taken 19540 times.
19608 if (thd->stmt_arena->is_stmt_prepare() && !thd->stmt_arena->is_repreparing &&
4575
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 6 times.
37 !initid.const_item) {
4576 31 udf_fun_guard.defer();
4577 31 return false;
4578 }
4579
2/2
✓ Branch 0 taken 19201 times.
✓ Branch 1 taken 339 times.
19540 if (u_d->func_init) {
4580
3/4
✓ Branch 0 taken 19201 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 462 times.
✓ Branch 3 taken 18739 times.
19201 if (call_init_func()) {
4581 462 return true;
4582 }
4583 18739 func->max_length = min<uint32>(initid.max_length, MAX_BLOB_WIDTH);
4584 18739 func->m_nullable = initid.maybe_null;
4585
4/4
✓ Branch 0 taken 8658 times.
✓ Branch 1 taken 10081 times.
✓ Branch 2 taken 3747 times.
✓ Branch 3 taken 4911 times.
18739 if (!initid.const_item && used_tables_cache == 0)
4586 3747 used_tables_cache = RAND_TABLE_BIT;
4587 18739 func->decimals = min<uint>(initid.decimals, DECIMAL_NOT_SPECIFIED);
4588 /*
4589 For UDFs of type string, override character set and collation from
4590 return value extension specification.
4591 */
4592
2/2
✓ Branch 0 taken 15812 times.
✓ Branch 1 taken 2926 times.
18739 if (result_type() == STRING_RESULT)
4593 15812 func->set_data_type_string(func->max_length,
4594 m_return_value_extension.charset_info);
4595 }
4596 /*
4597 UDF initialization complete so leave the freeing up resources to
4598 cleanup method.
4599 */
4600 19075 udf_fun_guard.defer();
4601 19078 return false;
4602 19574 }
4603
4604 19201 bool udf_handler::call_init_func() {
4605 char init_msg_buff[MYSQL_ERRMSG_SIZE];
4606 19201 *init_msg_buff = '\0';
4607 19201 char *to = num_buffer;
4608 19201 f_args.extension = &m_args_extension;
4609
4610
2/2
✓ Branch 0 taken 24995 times.
✓ Branch 1 taken 19201 times.
44196 for (uint i = 0; i < f_args.arg_count; i++) {
4611 /*
4612 For a constant argument i, args->args[i] points to the argument value.
4613 For non-constant, args->args[i] is NULL.
4614 */
4615 24995 f_args.args[i] = nullptr; // Non-const unless updated below
4616
4617 24995 f_args.lengths[i] = args[i]->max_length;
4618 24995 f_args.maybe_null[i] = args[i]->m_nullable;
4619 24995 f_args.attributes[i] = const_cast<char *>(args[i]->item_name.ptr());
4620 24995 f_args.attribute_lengths[i] = args[i]->item_name.length();
4621 24995 m_args_extension.charset_info[i] = args[i]->collation.collation;
4622
4623
6/8
✓ Branch 0 taken 24995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24666 times.
✓ Branch 3 taken 329 times.
✓ Branch 4 taken 24666 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 24666 times.
✓ Branch 7 taken 329 times.
24995 if (args[i]->const_for_execution() && !args[i]->has_subquery()) {
4624
4/6
✓ Branch 0 taken 24666 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21224 times.
✓ Branch 3 taken 3437 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
24666 switch (args[i]->result_type()) {
4625 21224 case STRING_RESULT:
4626 case DECIMAL_RESULT: {
4627
1/2
✓ Branch 0 taken 21224 times.
✗ Branch 1 not taken.
21224 get_string(i);
4628 21224 break;
4629 }
4630 3437 case INT_RESULT:
4631
1/2
✓ Branch 0 taken 3437 times.
✗ Branch 1 not taken.
3437 *((longlong *)to) = args[i]->val_int();
4632
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3436 times.
3437 if (args[i]->null_value) continue;
4633 3436 f_args.args[i] = to;
4634 3436 to += ALIGN_SIZE(sizeof(longlong));
4635 3436 break;
4636 5 case REAL_RESULT:
4637
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 *((double *)to) = args[i]->val_real();
4638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (args[i]->null_value) continue;
4639 5 f_args.args[i] = to;
4640 5 to += ALIGN_SIZE(sizeof(double));
4641 5 break;
4642 case ROW_RESULT:
4643 default:
4644 // This case should never be chosen
4645 assert(0);
4646 break;
4647 }
4648 }
4649 }
4650 19201 Udf_func_init init = u_d->func_init;
4651
3/4
✓ Branch 0 taken 19200 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 462 times.
✓ Branch 3 taken 18738 times.
19201 if ((error = (uchar)init(&initid, &f_args, init_msg_buff))) {
4652
1/2
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
462 my_error(ER_CANT_INITIALIZE_UDF, MYF(0), u_d->name.str, init_msg_buff);
4653 462 return true;
4654 }
4655 18738 m_init_func_called = true;
4656 18738 return false;
4657 }
4658
4659 19271 bool udf_handler::get_arguments() {
4660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19271 times.
19271 if (error) return true; // Got an error earlier
4661 19271 char *to = num_buffer;
4662
2/2
✓ Branch 0 taken 24271 times.
✓ Branch 1 taken 19271 times.
43542 for (uint i = 0; i < f_args.arg_count; i++) {
4663 24271 f_args.args[i] = nullptr;
4664
4/5
✓ Branch 0 taken 20939 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3258 times.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
24271 switch (f_args.arg_type[i]) {
4665 20939 case STRING_RESULT:
4666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20939 times.
20939 if (get_and_convert_string(i)) return true;
4667 20939 break;
4668 3 case DECIMAL_RESULT:
4669 3 get_string(i);
4670 3 break;
4671 3258 case INT_RESULT:
4672 3258 *((longlong *)to) = args[i]->val_int();
4673
2/2
✓ Branch 0 taken 3249 times.
✓ Branch 1 taken 9 times.
3258 if (!args[i]->null_value) {
4674 3249 f_args.args[i] = to;
4675 3249 to += ALIGN_SIZE(sizeof(longlong));
4676 }
4677 3258 break;
4678 71 case REAL_RESULT:
4679 71 *((double *)to) = args[i]->val_real();
4680
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 3 times.
71 if (!args[i]->null_value) {
4681 68 f_args.args[i] = to;
4682 68 to += ALIGN_SIZE(sizeof(double));
4683 }
4684 71 break;
4685 case ROW_RESULT:
4686 default:
4687 // This case should never be chosen
4688 assert(0);
4689 break;
4690 }
4691 }
4692 19271 return false;
4693 }
4694
4695 85 double udf_handler::val_real(bool *null_value) {
4696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 assert(is_initialized());
4697 85 is_null = 0;
4698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 if (get_arguments()) {
4699 *null_value = true;
4700 return 0.0;
4701 }
4702 85 Udf_func_double func = (Udf_func_double)u_d->func;
4703 85 double tmp = func(&initid, &f_args, &is_null, &error);
4704
4/4
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 76 times.
85 if (is_null || error) {
4705 9 *null_value = true;
4706 9 return 0.0;
4707 }
4708 76 *null_value = false;
4709 76 return tmp;
4710 }
4711
4712 3212 longlong udf_handler::val_int(bool *null_value) {
4713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3212 times.
3212 assert(is_initialized());
4714 3212 is_null = 0;
4715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3212 times.
3212 if (get_arguments()) {
4716 *null_value = true;
4717 return 0LL;
4718 }
4719
1/2
✓ Branch 0 taken 3212 times.
✗ Branch 1 not taken.
3212 DEBUG_SYNC(current_thd, "execute_uninstall_component");
4720 3212 Udf_func_longlong func = (Udf_func_longlong)u_d->func;
4721 3212 longlong tmp = func(&initid, &f_args, &is_null, &error);
4722
4/4
✓ Branch 0 taken 3204 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 3162 times.
3212 if (is_null || error) {
4723 50 *null_value = true;
4724 50 return 0LL;
4725 }
4726 3162 *null_value = false;
4727 3162 return tmp;
4728 }
4729
4730 /**
4731 @return
4732 (String*)NULL in case of NULL values
4733 */
4734 15899 String *udf_handler::val_str(String *str, String *save_str) {
4735 15899 uchar is_null_tmp = 0;
4736 ulong res_length;
4737
1/2
✓ Branch 0 taken 15902 times.
✗ Branch 1 not taken.
15899 DBUG_TRACE;
4738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15902 times.
15902 assert(is_initialized());
4739
4740
2/4
✓ Branch 0 taken 15900 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15900 times.
15902 if (get_arguments()) return nullptr;
4741
4742
3/6
✓ Branch 0 taken 15900 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15902 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15903 times.
✗ Branch 5 not taken.
15900 DEBUG_SYNC(current_thd, "before_string_udf_execution");
4743 15903 Udf_func_string func = reinterpret_cast<Udf_func_string>(u_d->func);
4744
4745
2/2
✓ Branch 0 taken 6278 times.
✓ Branch 1 taken 9625 times.
15903 if ((res_length = str->alloced_length()) <
4746 MAX_FIELD_WIDTH) { // This happens VERY seldom
4747
2/4
✓ Branch 0 taken 6278 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6278 times.
6278 if (str->alloc(MAX_FIELD_WIDTH)) {
4748 error = 1;
4749 return nullptr;
4750 }
4751 }
4752 char *res =
4753
1/2
✓ Branch 0 taken 15903 times.
✗ Branch 1 not taken.
15903 func(&initid, &f_args, str->ptr(), &res_length, &is_null_tmp, &error);
4754
3/8
✓ Branch 0 taken 15903 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15903 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15903 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
15903 DBUG_PRINT("info", ("udf func returned, res_length: %lu", res_length));
4755
6/6
✓ Branch 0 taken 15784 times.
✓ Branch 1 taken 119 times.
✓ Branch 2 taken 15674 times.
✓ Branch 3 taken 110 times.
✓ Branch 4 taken 302 times.
✓ Branch 5 taken 15372 times.
15903 if (is_null_tmp || !res || error) // The !res is for safety
4756 {
4757
3/8
✓ Branch 0 taken 531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 531 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 531 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
531 DBUG_PRINT("info", ("Null or error"));
4758 531 return nullptr;
4759 }
4760
4761
1/2
✓ Branch 0 taken 15371 times.
✗ Branch 1 not taken.
15372 String *res_str = result_string(res, res_length, str, save_str);
4762
3/8
✓ Branch 0 taken 15372 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15372 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15372 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
15371 DBUG_PRINT("exit", ("res_str: %s", res_str->ptr()));
4763 15372 return res_str;
4764 15903 }
4765
4766 /*
4767 For the moment, UDF functions are returning DECIMAL values as strings
4768 */
4769
4770 my_decimal *udf_handler::val_decimal(bool *null_value, my_decimal *dec_buf) {
4771 char buf[DECIMAL_MAX_STR_LENGTH + 1];
4772 ulong res_length = DECIMAL_MAX_STR_LENGTH;
4773
4774 assert(is_initialized());
4775
4776 if (get_arguments()) {
4777 *null_value = true;
4778 return nullptr;
4779 }
4780 Udf_func_string func = reinterpret_cast<Udf_func_string>(u_d->func);
4781
4782 char *res = func(&initid, &f_args, buf, &res_length, &is_null, &error);
4783 if (is_null || error) {
4784 *null_value = true;
4785 return nullptr;
4786 }
4787 const char *end = res + res_length;
4788 str2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf, &end);
4789 return dec_buf;
4790 }
4791
4792 48 void udf_handler::clear() {
4793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 assert(is_initialized());
4794 48 is_null = 0;
4795 48 Udf_func_clear func = u_d->func_clear;
4796 48 func(&initid, &is_null, &error);
4797 48 }
4798
4799 74 void udf_handler::add(bool *null_value) {
4800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 assert(is_initialized());
4801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (get_arguments()) {
4802 *null_value = true;
4803 return;
4804 }
4805 74 Udf_func_add func = u_d->func_add;
4806 74 func(&initid, &f_args, &is_null, &error);
4807
2/4
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 74 times.
74 *null_value = (bool)(is_null || error);
4808 }
4809
4810 /**
4811 Process the result string returned by the udf() method. The charset
4812 info might have changed therefore updates the same String. If user
4813 used the input String as result string then return the same.
4814
4815 @param [in] res the result string returned by the udf() method.
4816 @param [in] res_length length of the string
4817 @param [out] str The input result string passed to the udf() method
4818 @param [out] save_str Keeps copy of the returned String
4819
4820 @returns A pointer to either the str or save_str that points
4821 to final result String
4822 */
4823 15371 String *udf_handler::result_string(const char *res, size_t res_length,
4824 String *str, String *save_str) {
4825 15371 const auto *charset = m_return_value_extension.charset_info;
4826 15371 String *res_str = nullptr;
4827
2/2
✓ Branch 0 taken 8918 times.
✓ Branch 1 taken 6454 times.
15371 if (res == str->ptr()) {
4828 8918 res_str = str;
4829 8918 res_str->length(res_length);
4830 8918 res_str->set_charset(charset);
4831 } else {
4832 6454 res_str = save_str;
4833 6454 res_str->set(res, res_length, charset);
4834 }
4835 15372 return res_str;
4836 }
4837
4838 /**
4839 Get the details of the input String arguments.
4840
4841 @param [in] index of the argument to be looked in the arguments array
4842 */
4843 21227 void udf_handler::get_string(uint index) {
4844 21227 String *res = args[index]->val_str(&buffers[index]);
4845
2/2
✓ Branch 0 taken 21139 times.
✓ Branch 1 taken 88 times.
21227 if (!args[index]->null_value) {
4846 21139 f_args.args[index] = res->ptr();
4847 21139 f_args.lengths[index] = res->length();
4848 } else {
4849 88 f_args.lengths[index] = 0;
4850 }
4851 21227 }
4852
4853 /**
4854 Get the details of the input String argument.
4855 If the charset of the input argument is not same as specified by the
4856 user then convert the String.
4857
4858 @param [in] index of the argument to be looked in the arguments array
4859
4860 @retval false Able to fetch the argument details
4861 @retval true Otherwise
4862 */
4863 20939 bool udf_handler::get_and_convert_string(uint index) {
4864 20939 String *res = args[index]->val_str(&buffers[index]);
4865
4866 /* m_args_extension.charset_info[index] is a legitimate charset */
4867
4/4
✓ Branch 0 taken 20879 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 20878 times.
✓ Branch 3 taken 1 times.
20939 if (res != nullptr && m_args_extension.charset_info[index] != nullptr) {
4868
2/2
✓ Branch 0 taken 1418 times.
✓ Branch 1 taken 19460 times.
20878 if (res->charset() != m_args_extension.charset_info[index]) {
4869 1418 String temp;
4870 uint dummy;
4871
2/4
✓ Branch 0 taken 1418 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1418 times.
1418 if (temp.copy(res->ptr(), res->length(), res->charset(),
4872 1418 m_args_extension.charset_info[index], &dummy)) {
4873 return true;
4874 }
4875 1418 *res = std::move(temp);
4876
1/2
✓ Branch 0 taken 1418 times.
✗ Branch 1 not taken.
1418 }
4877 }
4878
2/2
✓ Branch 0 taken 20879 times.
✓ Branch 1 taken 60 times.
20939 if (!args[index]->null_value) {
4879 20879 f_args.args[index] = res->c_ptr_safe();
4880 20879 f_args.lengths[index] = res->length();
4881 } else {
4882 60 f_args.lengths[index] = 0;
4883 }
4884 20939 return false;
4885 }
4886
4887 19624 bool Item_udf_func::itemize(Parse_context *pc, Item **res) {
4888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19623 times.
19624 if (skip_itemize(res)) return false;
4889
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19622 times.
19623 if (super::itemize(pc, res)) return true;
4890 19622 pc->thd->lex->set_has_udf();
4891 19621 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UDF);
4892 19625 pc->thd->lex->safe_to_cache_query = false;
4893 19625 return false;
4894 }
4895
4896 19615 void Item_udf_func::cleanup() {
4897 19615 udf.cleanup();
4898 19616 str_value.mem_free();
4899 19616 Item_func::cleanup();
4900 19616 }
4901
4902 14 void Item_udf_func::print(const THD *thd, String *str,
4903 enum_query_type query_type) const {
4904
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 str->append(func_name());
4905 14 str->append('(');
4906
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (uint i = 0; i < arg_count; i++) {
4907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (i != 0) str->append(',');
4908 14 args[i]->print_item_w_name(thd, str, query_type);
4909 }
4910 14 str->append(')');
4911 14 }
4912
4913 67 double Item_func_udf_float::val_real() {
4914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 assert(fixed == 1);
4915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 DBUG_PRINT("info", ("result_type: %d arg_count: %d", args[0]->result_type(),
4916 arg_count));
4917 67 return udf.val_real(&null_value);
4918 }
4919
4920 String *Item_func_udf_float::val_str(String *str) {
4921 assert(fixed == 1);
4922 double nr = val_real();
4923 if (null_value) return nullptr; /* purecov: inspected */
4924 str->set_real(nr, decimals, &my_charset_bin);
4925 return str;
4926 }
4927
4928 3186 longlong Item_func_udf_int::val_int() {
4929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3186 times.
3186 assert(fixed == 1);
4930 3186 return udf.val_int(&null_value);
4931 }
4932
4933 42 String *Item_func_udf_int::val_str(String *str) {
4934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 assert(fixed == 1);
4935 42 longlong nr = val_int();
4936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (null_value) return nullptr;
4937 42 str->set_int(nr, unsigned_flag, &my_charset_bin);
4938 42 return str;
4939 }
4940
4941 longlong Item_func_udf_decimal::val_int() {
4942 my_decimal dec_buf, *dec = udf.val_decimal(&null_value, &dec_buf);
4943 longlong result;
4944 if (null_value) return 0;
4945 my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
4946 return result;
4947 }
4948
4949 double Item_func_udf_decimal::val_real() {
4950 my_decimal dec_buf, *dec = udf.val_decimal(&null_value, &dec_buf);
4951 double result;
4952 if (null_value) return 0.0;
4953 my_decimal2double(E_DEC_FATAL_ERROR, dec, &result);
4954 return result;
4955 }
4956
4957 my_decimal *Item_func_udf_decimal::val_decimal(my_decimal *dec_buf) {
4958 return udf.val_decimal(&null_value, dec_buf);
4959 }
4960
4961 String *Item_func_udf_decimal::val_str(String *str) {
4962 my_decimal dec_buf, *dec = udf.val_decimal(&null_value, &dec_buf);
4963 if (null_value) return nullptr;
4964 if (str->length() < DECIMAL_MAX_STR_LENGTH)
4965 str->length(DECIMAL_MAX_STR_LENGTH);
4966 my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, false, &dec_buf);
4967 my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, str);
4968 return str;
4969 }
4970
4971 bool Item_func_udf_decimal::resolve_type(THD *) {
4972 set_data_type(MYSQL_TYPE_NEWDECIMAL);
4973 fix_num_length_and_dec();
4974 return false;
4975 }
4976
4977 /* Default max_length is max argument length */
4978
4979 16194 bool Item_func_udf_str::resolve_type(THD *) {
4980 16194 uint result_length = 0;
4981
2/2
✓ Branch 0 taken 16608 times.
✓ Branch 1 taken 16194 times.
32802 for (uint i = 0; i < arg_count; i++)
4982 16608 result_length = max(result_length, args[i]->max_length);
4983 // If the UDF has an init function, this may be overridden later.
4984 16194 set_data_type_string(result_length, &my_charset_bin);
4985 16194 return false;
4986 }
4987
4988 15899 String *Item_func_udf_str::val_str(String *str) {
4989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15899 times.
15899 assert(fixed == 1);
4990 15899 String *res = udf.val_str(str, &str_value);
4991 15903 null_value = !res;
4992 15903 return res;
4993 }
4994
4995 19525 bool Item_source_pos_wait::itemize(Parse_context *pc, Item **res) {
4996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19525 times.
19525 if (skip_itemize(res)) return false;
4997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19525 times.
19525 if (super::itemize(pc, res)) return true;
4998 19525 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
4999 19525 pc->thd->lex->safe_to_cache_query = false;
5000 19525 return false;
5001 }
5002
5003 /**
5004 Wait until we are at or past the given position in the master binlog
5005 on the slave.
5006 */
5007
5008 19520 longlong Item_source_pos_wait::val_int() {
5009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19520 times.
19520 assert(fixed == 1);
5010 19520 THD *thd = current_thd;
5011 19520 String *log_name = args[0]->val_str(&value);
5012 19520 int event_count = 0;
5013
5014 19520 null_value = false;
5015
4/8
✓ Branch 0 taken 19520 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19520 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19520 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 19520 times.
19520 if (thd->slave_thread || !log_name || !log_name->length()) {
5016 null_value = true;
5017 return 0;
5018 }
5019 Master_info *mi;
5020 19520 longlong pos = (ulong)args[1]->val_int();
5021
2/2
✓ Branch 0 taken 19511 times.
✓ Branch 1 taken 9 times.
19520 double timeout = (arg_count >= 3) ? args[2]->val_real() : 0;
5022
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 19515 times.
19520 if (timeout < 0) {
5023
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (thd->is_strict_mode()) {
5024 3 my_error(ER_WRONG_ARGUMENTS, MYF(0), "SOURCE_POS_WAIT.");
5025 } else {
5026 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
5027 ER_THD(thd, ER_WRONG_ARGUMENTS), "SOURCE_POS_WAIT.");
5028 2 null_value = true;
5029 }
5030 5 return 0;
5031 }
5032
5033 19515 channel_map.rdlock();
5034
5035
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 19294 times.
19515 if (arg_count == 4) {
5036 String *channel_str;
5037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 221 times.
221 if (!(channel_str = args[3]->val_str(&value))) {
5038 null_value = true;
5039 return 0;
5040 }
5041
5042 221 mi = channel_map.get_mi(channel_str->ptr());
5043
5044 } else {
5045
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 19290 times.
19294 if (channel_map.get_num_instances() > 1) {
5046 4 mi = nullptr;
5047 4 my_error(ER_SLAVE_MULTIPLE_CHANNELS_CMD, MYF(0));
5048 } else
5049 19290 mi = channel_map.get_default_channel_mi();
5050 }
5051
5052
2/2
✓ Branch 0 taken 19507 times.
✓ Branch 1 taken 8 times.
19515 if (mi != nullptr) mi->inc_reference();
5053
5054 19515 channel_map.unlock();
5055
5056
6/6
✓ Branch 0 taken 19507 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 19485 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 19485 times.
19515 if (mi == nullptr || (event_count = mi->rli->wait_for_pos(thd, log_name, pos,
5057 timeout)) == -2) {
5058 30 null_value = true;
5059 30 event_count = 0;
5060 }
5061
5062
2/2
✓ Branch 0 taken 19507 times.
✓ Branch 1 taken 8 times.
19515 if (mi != nullptr) mi->dec_reference();
5063 19515 return event_count;
5064 }
5065
5066 7 longlong Item_master_pos_wait::val_int() {
5067 7 push_deprecated_warn(current_thd, "MASTER_POS_WAIT", "SOURCE_POS_WAIT");
5068 7 return Item_source_pos_wait::val_int();
5069 }
5070
5071 2338 bool Item_wait_for_executed_gtid_set::itemize(Parse_context *pc, Item **res) {
5072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2338 times.
2338 if (skip_itemize(res)) return false;
5073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2338 times.
2338 if (super::itemize(pc, res)) return true;
5074 /*
5075 It is unsafe because the return value depends on timing. If the timeout
5076 happens, the return value is different from the one in which the function
5077 returns with success.
5078 */
5079 2338 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5080 2338 pc->thd->lex->safe_to_cache_query = false;
5081 2338 return false;
5082 }
5083
5084 /**
5085 Wait until the given gtid_set is found in the executed gtid_set independent
5086 of the slave threads.
5087 */
5088 4150 longlong Item_wait_for_executed_gtid_set::val_int() {
5089
1/2
✓ Branch 0 taken 4150 times.
✗ Branch 1 not taken.
4150 DBUG_TRACE;
5090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4150 times.
4150 assert(fixed);
5091
1/2
✓ Branch 0 taken 4150 times.
✗ Branch 1 not taken.
4150 THD *thd = current_thd;
5092
5093 4150 null_value = false;
5094
5095
1/2
✓ Branch 0 taken 4150 times.
✗ Branch 1 not taken.
4150 String *gtid_text = args[0]->val_str(&value);
5096
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4146 times.
4150 if (gtid_text == nullptr) {
5097 /*
5098 Usually, an argument that is NULL causes an SQL function to return NULL,
5099 however since this is a function with side-effects, a NULL value is
5100 treated as an error.
5101 */
5102
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (!thd->is_error()) {
5103
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_MALFORMED_GTID_SET_SPECIFICATION, MYF(0), "NULL");
5104 }
5105 4 return error_int();
5106 }
5107
5108 // Waiting for a GTID in a slave thread could cause the slave to
5109 // hang/deadlock.
5110 // @todo: Return error instead of NULL
5111
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4144 times.
4146 if (thd->slave_thread) {
5112 2 return error_int();
5113 }
5114
5115
1/2
✓ Branch 0 taken 4144 times.
✗ Branch 1 not taken.
4144 Gtid_set wait_for_gtid_set(global_sid_map, nullptr);
5116
5117
1/2
✓ Branch 0 taken 4144 times.
✗ Branch 1 not taken.
4144 global_sid_lock->rdlock();
5118
3/4
✓ Branch 0 taken 4144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4140 times.
4144 if (global_gtid_mode.get() == Gtid_mode::OFF) {
5119
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 global_sid_lock->unlock();
5120
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_GTID_MODE_OFF, MYF(0), "use WAIT_FOR_EXECUTED_GTID_SET");
5121 4 return error_int();
5122 }
5123
5124
4/6
✓ Branch 0 taken 4140 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 4137 times.
4140 if (wait_for_gtid_set.add_gtid_text(gtid_text->c_ptr_safe()) !=
5125 RETURN_STATUS_OK) {
5126
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 global_sid_lock->unlock();
5127 // Error has already been generated.
5128 3 return error_int();
5129 }
5130
5131 // Cannot wait for a GTID that the thread owns since that would
5132 // immediately deadlock.
5133
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4135 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4136 times.
4139 if (thd->owned_gtid.sidno > 0 &&
5134
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 wait_for_gtid_set.contains_gtid(thd->owned_gtid)) {
5135 char buf[Gtid::MAX_TEXT_LENGTH + 1];
5136
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 thd->owned_gtid.to_string(global_sid_map, buf);
5137
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 global_sid_lock->unlock();
5138
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_CANT_WAIT_FOR_EXECUTED_GTID_SET_WHILE_OWNING_A_GTID, MYF(0),
5139 buf);
5140 1 return error_int();
5141 }
5142
5143
1/2
✓ Branch 0 taken 4136 times.
✗ Branch 1 not taken.
4136 gtid_state->begin_gtid_wait();
5144
5145
3/4
✓ Branch 0 taken 4065 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 4065 times.
✗ Branch 3 not taken.
4136 double timeout = (arg_count == 2) ? args[1]->val_real() : 0;
5146
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4130 times.
4136 if (timeout < 0) {
5147
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (thd->is_strict_mode()) {
5148
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_WRONG_ARGUMENTS, MYF(0), "WAIT_FOR_EXECUTED_GTID_SET.");
5149 } else {
5150
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
5151 ER_THD(thd, ER_WRONG_ARGUMENTS),
5152 "WAIT_FOR_EXECUTED_GTID_SET.");
5153 }
5154
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 gtid_state->end_gtid_wait();
5155
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 global_sid_lock->unlock();
5156 6 return error_int();
5157 }
5158
5159
1/2
✓ Branch 0 taken 4130 times.
✗ Branch 1 not taken.
4130 bool result = gtid_state->wait_for_gtid_set(thd, &wait_for_gtid_set, timeout);
5160
1/2
✓ Branch 0 taken 4130 times.
✗ Branch 1 not taken.
4130 global_sid_lock->unlock();
5161
1/2
✓ Branch 0 taken 4130 times.
✗ Branch 1 not taken.
4130 gtid_state->end_gtid_wait();
5162
5163 4130 return result;
5164 4150 }
5165
5166 19 Item_master_gtid_set_wait::Item_master_gtid_set_wait(const POS &pos, Item *a)
5167 19 : Item_int_func(pos, a) {
5168
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
19 push_deprecated_warn(current_thd, "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS",
5169 "WAIT_FOR_EXECUTED_GTID_SET");
5170 19 }
5171
5172 1903 Item_master_gtid_set_wait::Item_master_gtid_set_wait(const POS &pos, Item *a,
5173 1903 Item *b)
5174 1903 : Item_int_func(pos, a, b) {
5175
2/4
✓ Branch 0 taken 1903 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1903 times.
✗ Branch 3 not taken.
1903 push_deprecated_warn(current_thd, "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS",
5176 "WAIT_FOR_EXECUTED_GTID_SET");
5177 1903 }
5178
5179 88 Item_master_gtid_set_wait::Item_master_gtid_set_wait(const POS &pos, Item *a,
5180 88 Item *b, Item *c)
5181 88 : Item_int_func(pos, a, b, c) {
5182
2/4
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
88 push_deprecated_warn(current_thd, "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS",
5183 "WAIT_FOR_EXECUTED_GTID_SET");
5184 88 }
5185
5186 2010 bool Item_master_gtid_set_wait::itemize(Parse_context *pc, Item **res) {
5187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2010 times.
2010 if (skip_itemize(res)) return false;
5188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2010 times.
2010 if (super::itemize(pc, res)) return true;
5189 2010 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5190 2010 pc->thd->lex->safe_to_cache_query = false;
5191 2010 return false;
5192 }
5193
5194 2007 longlong Item_master_gtid_set_wait::val_int() {
5195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2007 times.
2007 assert(fixed);
5196
1/2
✓ Branch 0 taken 2007 times.
✗ Branch 1 not taken.
2007 DBUG_TRACE;
5197 2007 int event_count = 0;
5198
5199 2007 null_value = false;
5200
5201
1/2
✓ Branch 0 taken 2007 times.
✗ Branch 1 not taken.
2007 String *gtid = args[0]->val_str(&value);
5202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2007 times.
2007 if (gtid == nullptr) {
5203 return error_int();
5204 }
5205
5206
1/2
✓ Branch 0 taken 2007 times.
✗ Branch 1 not taken.
2007 THD *thd = current_thd;
5207 2007 Master_info *mi = nullptr;
5208
3/4
✓ Branch 0 taken 1989 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 1989 times.
✗ Branch 3 not taken.
2007 double timeout = (arg_count >= 2) ? args[1]->val_real() : 0;
5209
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2003 times.
2007 if (timeout < 0) {
5210
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (thd->is_strict_mode()) {
5211
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_WRONG_ARGUMENTS, MYF(0),
5212 "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS.");
5213 } else {
5214
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
5215 ER_THD(thd, ER_WRONG_ARGUMENTS),
5216 "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS.");
5217 }
5218 4 return error_int();
5219 }
5220
5221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2003 times.
2003 if (thd->slave_thread) {
5222 return error_int();
5223 }
5224
5225
1/2
✓ Branch 0 taken 2003 times.
✗ Branch 1 not taken.
2003 channel_map.rdlock();
5226
5227 /* If replication channel is mentioned */
5228
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 1916 times.
2003 if (arg_count == 3) {
5229 String *channel_str;
5230
2/4
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 87 times.
87 if (!(channel_str = args[2]->val_str(&value))) {
5231 channel_map.unlock();
5232 return error_int();
5233 }
5234
1/2
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
87 mi = channel_map.get_mi(channel_str->ptr());
5235 } else {
5236
3/4
✓ Branch 0 taken 1916 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1913 times.
1916 if (channel_map.get_num_instances() > 1) {
5237
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 channel_map.unlock();
5238 3 mi = nullptr;
5239
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_SLAVE_MULTIPLE_CHANNELS_CMD, MYF(0));
5240 3 return error_int();
5241 } else
5242
1/2
✓ Branch 0 taken 1913 times.
✗ Branch 1 not taken.
1913 mi = channel_map.get_default_channel_mi();
5243 }
5244
5245
4/4
✓ Branch 0 taken 1999 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1999 times.
3999 if ((mi != nullptr) &&
5246
3/4
✓ Branch 0 taken 1999 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1998 times.
1999 mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type() >
5247 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF) {
5248
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_CANT_SET_ANONYMOUS_TO_GTID_AND_WAIT_UNTIL_SQL_THD_AFTER_GTIDS,
5249 MYF(0));
5250
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.unlock();
5251 1 return error_int();
5252 }
5253
3/4
✓ Branch 0 taken 1999 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1998 times.
1999 if (global_gtid_mode.get() == Gtid_mode::OFF) {
5254
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.unlock();
5255 1 return error_int();
5256 }
5257
1/2
✓ Branch 0 taken 1998 times.
✗ Branch 1 not taken.
1998 gtid_state->begin_gtid_wait();
5258
5259
1/2
✓ Branch 0 taken 1998 times.
✗ Branch 1 not taken.
1998 if (mi != nullptr) mi->inc_reference();
5260
5261
1/2
✓ Branch 0 taken 1998 times.
✗ Branch 1 not taken.
1998 channel_map.unlock();
5262
5263 1998 bool null_result = false;
5264
5265
2/4
✓ Branch 0 taken 1998 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1998 times.
✗ Branch 3 not taken.
1998 if (mi != nullptr && mi->rli != nullptr) {
5266
1/2
✓ Branch 0 taken 1998 times.
✗ Branch 1 not taken.
1998 event_count = mi->rli->wait_for_gtid_set(thd, gtid, timeout);
5267
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1997 times.
1998 if (event_count == -2) {
5268 1 null_result = true;
5269 }
5270 } else {
5271 /*
5272 Replication has not been set up, we should return NULL;
5273 */
5274 null_result = true;
5275 }
5276
1/2
✓ Branch 0 taken 1998 times.
✗ Branch 1 not taken.
1998 if (mi != nullptr) mi->dec_reference();
5277
5278
1/2
✓ Branch 0 taken 1998 times.
✗ Branch 1 not taken.
1998 gtid_state->end_gtid_wait();
5279
5280
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1997 times.
1998 return null_result ? error_int() : event_count;
5281 2007 }
5282
5283 /**
5284 Return 1 if both arguments are Gtid_sets and the first is a subset
5285 of the second. Generate an error if any of the arguments is not a
5286 Gtid_set.
5287 */
5288 5914 longlong Item_func_gtid_subset::val_int() {
5289
1/2
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
5914 DBUG_TRACE;
5290
5291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5914 times.
5914 assert(fixed);
5292
5293 5914 null_value = false;
5294
5295 // Evaluate strings without lock
5296
1/2
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
5914 String *string1 = args[0]->val_str(&buf1);
5297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5914 times.
5914 if (string1 == nullptr) {
5298 return error_int();
5299 }
5300
1/2
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
5914 String *string2 = args[1]->val_str(&buf2);
5301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5914 times.
5914 if (string2 == nullptr) {
5302 return error_int();
5303 }
5304
5305
1/2
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
5914 const char *charp1 = string1->c_ptr_safe();
5306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5914 times.
5914 assert(charp1 != nullptr);
5307
1/2
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
5914 const char *charp2 = string2->c_ptr_safe();
5308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5914 times.
5914 assert(charp2 != nullptr);
5309 5914 int ret = 1;
5310 enum_return_status status;
5311
5312
1/2
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
5914 Sid_map sid_map(nullptr /*no rwlock*/);
5313 // compute sets while holding locks
5314
1/2
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
5914 const Gtid_set sub_set(&sid_map, charp1, &status);
5315
1/2
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
5914 if (status == RETURN_STATUS_OK) {
5316
1/2
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
5914 const Gtid_set super_set(&sid_map, charp2, &status);
5317
1/2
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
5914 if (status == RETURN_STATUS_OK) {
5318
3/4
✓ Branch 0 taken 5914 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5907 times.
✓ Branch 3 taken 7 times.
5914 ret = sub_set.is_subset(&super_set) ? 1 : 0;
5319 }
5320 5914 }
5321 5914 return ret;
5322 5914 }
5323
5324 /**
5325 Enables a session to wait on a condition until a timeout or a network
5326 disconnect occurs.
5327
5328 @remark The connection is polled every m_interrupt_interval nanoseconds.
5329 */
5330
5331 class Interruptible_wait {
5332 THD *m_thd;
5333 struct timespec m_abs_timeout;
5334 static const ulonglong m_interrupt_interval;
5335
5336 public:
5337 10696 Interruptible_wait(THD *thd) : m_thd(thd) {}
5338
5339 ~Interruptible_wait() = default;
5340
5341 public:
5342 /**
5343 Set the absolute timeout.
5344
5345 @param timeout The amount of time in nanoseconds to wait
5346 */
5347 10683 void set_timeout(ulonglong timeout) {
5348 /*
5349 Calculate the absolute system time at the start so it can
5350 be controlled in slices. It relies on the fact that once
5351 the absolute time passes, the timed wait call will fail
5352 automatically with a timeout error.
5353 */
5354 10683 set_timespec_nsec(&m_abs_timeout, timeout);
5355 10683 }
5356
5357 /** The timed wait. */
5358 int wait(mysql_cond_t *, mysql_mutex_t *);
5359 };
5360
5361 /** Time to wait before polling the connection status. */
5362 const ulonglong Interruptible_wait::m_interrupt_interval = 5 * 1000000000ULL;
5363
5364 /**
5365 Wait for a given condition to be signaled.
5366
5367 @param cond The condition variable to wait on.
5368 @param mutex The associated mutex.
5369
5370 @remark The absolute timeout is preserved across calls.
5371
5372 @retval return value from mysql_cond_timedwait
5373 */
5374
5375 10713 int Interruptible_wait::wait(mysql_cond_t *cond, mysql_mutex_t *mutex) {
5376 int error;
5377 struct timespec timeout;
5378
5379 while (true) {
5380 /* Wait for a fixed interval. */
5381
1/2
✓ Branch 0 taken 10713 times.
✗ Branch 1 not taken.
10713 set_timespec_nsec(&timeout, m_interrupt_interval);
5382
5383 /* But only if not past the absolute timeout. */
5384
2/2
✓ Branch 0 taken 10657 times.
✓ Branch 1 taken 56 times.
10713 if (cmp_timespec(&timeout, &m_abs_timeout) > 0) timeout = m_abs_timeout;
5385
5386
1/2
✓ Branch 0 taken 10684 times.
✗ Branch 1 not taken.
10713 error = mysql_cond_timedwait(cond, mutex, &timeout);
5387
2/2
✓ Branch 0 taken 10652 times.
✓ Branch 1 taken 32 times.
10684 if (is_timeout(error)) {
5388 /* Return error if timed out or connection is broken. */
5389
7/8
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 10616 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 30 times.
✓ Branch 6 taken 10622 times.
✓ Branch 7 taken 30 times.
10652 if (!cmp_timespec(&timeout, &m_abs_timeout) || !m_thd->is_connected())
5390 10622 break;
5391 }
5392 /* Otherwise, propagate status to the caller. */
5393 else
5394 32 break;
5395 }
5396
5397 10654 return error;
5398 }
5399
5400 /*
5401 User-level locks implementation.
5402 */
5403
5404 /**
5405 For locks with EXPLICIT duration, MDL returns a new ticket
5406 every time a lock is granted. This allows to implement recursive
5407 locks without extra allocation or additional data structures, such
5408 as below. However, if there are too many tickets in the same
5409 MDL_context, MDL_context::find_ticket() is getting too slow,
5410 since it's using a linear search.
5411 This is why a separate structure is allocated for a user
5412 level lock held by connection, and before requesting a new lock from MDL,
5413 GET_LOCK() checks thd->ull_hash if such lock is already granted,
5414 and if so, simply increments a reference counter.
5415 */
5416
5417 struct User_level_lock {
5418 MDL_ticket *ticket;
5419 uint refs;
5420 };
5421
5422 /**
5423 Release all user level locks for this THD.
5424 */
5425
5426 1144278 void mysql_ull_cleanup(THD *thd) {
5427
1/2
✓ Branch 0 taken 1144750 times.
✗ Branch 1 not taken.
1144278 DBUG_TRACE;
5428
5429
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1144000 times.
1144814 for (const auto &key_and_value : thd->ull_hash) {
5430 64 User_level_lock *ull = key_and_value.second;
5431
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 thd->mdl_context.release_lock(ull->ticket);
5432
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 my_free(ull);
5433 }
5434
5435 1144000 thd->ull_hash.clear();
5436 1144457 }
5437
5438 /**
5439 Set explicit duration for metadata locks corresponding to
5440 user level locks to protect them from being released at the end
5441 of transaction.
5442 */
5443
5444 2 void mysql_ull_set_explicit_lock_duration(THD *thd) {
5445
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 DBUG_TRACE;
5446
5447
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 for (const auto &key_and_value : thd->ull_hash) {
5448 3 User_level_lock *ull = key_and_value.second;
5449
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 thd->mdl_context.set_lock_duration(ull->ticket, MDL_EXPLICIT);
5450 }
5451 2 }
5452
5453 /**
5454 When MDL detects a lock wait timeout, it pushes an error into the statement
5455 diagnostics area. For GET_LOCK(), lock wait timeout is not an error, but a
5456 special return value (0). NULL is returned in case of error. Capture and
5457 suppress lock wait timeout.
5458 We also convert ER_LOCK_DEADLOCK error to ER_USER_LOCK_DEADLOCK error.
5459 The former means that implicit rollback of transaction has occurred
5460 which doesn't (and should not) happen when we get deadlock while waiting
5461 for user-level lock.
5462 */
5463
5464 class User_level_lock_wait_error_handler : public Internal_error_handler {
5465 public:
5466 6510 User_level_lock_wait_error_handler() : m_lock_wait_timeout(false) {}
5467
5468 28 bool got_timeout() const { return m_lock_wait_timeout; }
5469
5470 32 bool handle_condition(THD *, uint sql_errno, const char *,
5471 Sql_condition::enum_severity_level *,
5472 const char *) override {
5473
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 18 times.
32 if (sql_errno == ER_LOCK_WAIT_TIMEOUT) {
5474 14 m_lock_wait_timeout = true;
5475 14 return true;
5476
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 14 times.
18 } else if (sql_errno == ER_LOCK_DEADLOCK) {
5477 4 my_error(ER_USER_LOCK_DEADLOCK, MYF(0));
5478 4 return true;
5479 }
5480
5481 14 return false;
5482 }
5483
5484 private:
5485 bool m_lock_wait_timeout;
5486 };
5487
5488 class MDL_lock_get_owner_thread_id_visitor : public MDL_context_visitor {
5489 public:
5490 125 MDL_lock_get_owner_thread_id_visitor() : m_owner_id(0) {}
5491
5492 59 void visit_context(const MDL_context *ctx) override {
5493 59 m_owner_id = ctx->get_owner()->get_thd()->thread_id();
5494 59 }
5495
5496 125 my_thread_id get_owner_id() const { return m_owner_id; }
5497
5498 private:
5499 my_thread_id m_owner_id;
5500 };
5501
5502 /**
5503 Helper function which checks if user-level lock name is acceptable
5504 and converts it to system charset (utf8). Error is emitted if name
5505 is not acceptable. Name is also lowercased to ensure that user-level
5506 lock names are treated in case-insensitive fashion even though MDL
5507 subsystem which used by implementation does binary comparison of keys.
5508
5509 @param buff Buffer for lowercased name in system charset of
5510 NAME_LEN + 1 bytes length.
5511 @param org_name Original string passed as name parameter to
5512 user-level lock function.
5513
5514 @return True in case of error, false on success.
5515 */
5516
5517 13085 static bool check_and_convert_ull_name(char *buff, const String *org_name) {
5518
6/6
✓ Branch 0 taken 13080 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 13076 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 13076 times.
13085 if (!org_name || !org_name->length()) {
5519
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 my_error(ER_USER_LOCK_WRONG_NAME, MYF(0), (org_name ? "" : "NULL"));
5520 9 return true;
5521 }
5522
5523 const char *well_formed_error_pos;
5524 const char *cannot_convert_error_pos;
5525 const char *from_end_pos;
5526 size_t bytes_copied;
5527
5528
1/2
✓ Branch 0 taken 13076 times.
✗ Branch 1 not taken.
13076 bytes_copied = well_formed_copy_nchars(
5529 system_charset_info, buff, NAME_LEN, org_name->charset(), org_name->ptr(),
5530 org_name->length(), NAME_CHAR_LEN, &well_formed_error_pos,
5531 &cannot_convert_error_pos, &from_end_pos);
5532
5533
5/6
✓ Branch 0 taken 13075 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 13075 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 13071 times.
26151 if (well_formed_error_pos || cannot_convert_error_pos ||
5534
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 13071 times.
13075 from_end_pos < org_name->ptr() + org_name->length()) {
5535
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 ErrConvString err(org_name);
5536
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_USER_LOCK_WRONG_NAME, MYF(0), err.ptr());
5537 5 return true;
5538 }
5539
5540 13071 buff[bytes_copied] = '\0';
5541
5542
1/2
✓ Branch 0 taken 13071 times.
✗ Branch 1 not taken.
13071 my_casedn_str(system_charset_info, buff);
5543
5544 13071 return false;
5545 }
5546
5547 7104 bool Item_func_get_lock::itemize(Parse_context *pc, Item **res) {
5548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7105 times.
7104 if (skip_itemize(res)) return false;
5549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7105 times.
7105 if (super::itemize(pc, res)) return true;
5550 7105 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5551 7105 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5552 7105 return false;
5553 }
5554
5555 /**
5556 Get a user level lock.
5557
5558 @note Sets null_value to true on error.
5559
5560 @note This means that SQL-function GET_LOCK() returns:
5561 1 - if lock was acquired.
5562 0 - if lock was not acquired due to timeout.
5563 NULL - in case of error such as bad lock name, deadlock,
5564 thread being killed (also error is emitted).
5565
5566 @retval
5567 1 : Got lock
5568 @retval
5569 0 : Timeout, error.
5570 */
5571
5572 6559 longlong Item_func_get_lock::val_int() {
5573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6559 times.
6559 assert(fixed == 1);
5574
1/2
✓ Branch 0 taken 6559 times.
✗ Branch 1 not taken.
6559 String *res = args[0]->val_str(&value);
5575
1/2
✓ Branch 0 taken 6559 times.
✗ Branch 1 not taken.
6559 ulonglong timeout = args[1]->val_int();
5576 char name[NAME_LEN + 1];
5577
1/2
✓ Branch 0 taken 6559 times.
✗ Branch 1 not taken.
6559 THD *thd = current_thd;
5578
1/2
✓ Branch 0 taken 6559 times.
✗ Branch 1 not taken.
6559 DBUG_TRACE;
5579
5580 6559 null_value = true;
5581
5582 #ifdef WITH_WSREP
5583 6559 bool block = false;
5584
5585
3/3
✓ Branch 0 taken 6557 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
6559 switch (pxc_strict_mode) {
5586 6557 case PXC_STRICT_MODE_DISABLED:
5587 case PXC_STRICT_MODE_MASTER:
5588 /* Do nothing */
5589 6557 break;
5590 1 case PXC_STRICT_MODE_PERMISSIVE:
5591
10/22
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
1 WSREP_WARN(
5592 "Percona-XtraDB-Cluster doesn't recommend use of"
5593 " GET_LOCK with pxc_strict_mode = PERMISSIVE");
5594
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_UNKNOWN_ERROR,
5595 "Percona-XtraDB-Cluster doesn't recommend use of"
5596 " GET_LOCK with pxc_strict_mode = PERMISSIVE");
5597 1 break;
5598 1 case PXC_STRICT_MODE_ENFORCING:
5599 default:
5600 1 block = true;
5601
13/28
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
1 WSREP_ERROR(
5602 "Percona-XtraDB-Cluster prohibits use of GET_LOCK"
5603 " with pxc_strict_mode = ENFORCING");
5604 char message[1024];
5605 1 sprintf(message,
5606 "Percona-XtraDB-Cluster prohibits use of GET_LOCK"
5607 " with pxc_strict_mode = ENFORCING");
5608
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_message(ER_UNKNOWN_ERROR, message, MYF(0));
5609 1 break;
5610 }
5611
5612
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6558 times.
6559 if (block) return 0;
5613 #endif /* WITH_WSREP */
5614
5615 /*
5616 In slave thread no need to get locks, everything is serialized. Anyway
5617 there is no way to make GET_LOCK() work on slave like it did on master
5618 (i.e. make it return exactly the same value) because we don't have the
5619 same other concurrent threads environment. No matter what we return here,
5620 it's not guaranteed to be same as on master. So we always return 1.
5621 */
5622
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6545 times.
6558 if (thd->slave_thread) {
5623 13 null_value = false;
5624 13 return 1;
5625 }
5626
5627
3/4
✓ Branch 0 taken 6545 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 6542 times.
6545 if (check_and_convert_ull_name(name, res)) return 0;
5628
5629
3/8
✓ Branch 0 taken 6542 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6542 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6542 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
6542 DBUG_PRINT("info", ("lock %s, thd=%lu", name, (ulong)thd->real_id));
5630
5631 /*
5632 Convert too big and negative timeout values to INT_MAX32.
5633 This gives robust, "infinite" wait on all platforms.
5634 */
5635
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6541 times.
6542 if (timeout > INT_MAX32) timeout = INT_MAX32;
5636
5637 6542 MDL_request ull_request;
5638
1/2
✓ Branch 0 taken 6542 times.
✗ Branch 1 not taken.
6542 MDL_REQUEST_INIT(&ull_request, MDL_key::USER_LEVEL_LOCK, "", name,
5639 MDL_EXCLUSIVE, MDL_EXPLICIT);
5640 13084 std::string ull_key(pointer_cast<const char *>(ull_request.key.ptr()),
5641
2/4
✓ Branch 0 taken 6542 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6542 times.
✗ Branch 3 not taken.
13084 ull_request.key.length());
5642
5643
1/2
✓ Branch 0 taken 6542 times.
✗ Branch 1 not taken.
6542 const auto it = thd->ull_hash.find(ull_key);
5644
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 6510 times.
6542 if (it != thd->ull_hash.end()) {
5645 /* Recursive lock. */
5646 32 it->second->refs++;
5647 32 null_value = false;
5648 32 return 1;
5649 }
5650
5651 13020 User_level_lock_wait_error_handler error_handler;
5652
5653
1/2
✓ Branch 0 taken 6510 times.
✗ Branch 1 not taken.
6510 thd->push_internal_handler(&error_handler);
5654 bool error =
5655
1/2
✓ Branch 0 taken 6510 times.
✗ Branch 1 not taken.
6510 thd->mdl_context.acquire_lock(&ull_request, static_cast<ulong>(timeout));
5656
1/2
✓ Branch 0 taken 6510 times.
✗ Branch 1 not taken.
6510 (void)thd->pop_internal_handler();
5657
5658
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 6482 times.
6510 if (error) {
5659 /*
5660 Return 0 in case of timeout and NULL in case of deadlock/other
5661 errors. In the latter case error (e.g. ER_USER_LOCK_DEADLOCK)
5662 will be reported as well.
5663 */
5664
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 if (error_handler.got_timeout()) null_value = false;
5665 28 return 0;
5666 }
5667
5668 6482 User_level_lock *ull = nullptr;
5669 6482 ull = reinterpret_cast<User_level_lock *>(
5670
1/2
✓ Branch 0 taken 6482 times.
✗ Branch 1 not taken.
6482 my_malloc(key_memory_User_level_lock, sizeof(User_level_lock), MYF(0)));
5671
5672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6482 times.
6482 if (ull == nullptr) {
5673 thd->mdl_context.release_lock(ull_request.ticket);
5674 return 0;
5675 }
5676
5677 6482 ull->ticket = ull_request.ticket;
5678 6482 ull->refs = 1;
5679
5680
1/2
✓ Branch 0 taken 6482 times.
✗ Branch 1 not taken.
6482 thd->ull_hash.emplace(ull_key, ull);
5681 6482 null_value = false;
5682
5683 6482 return 1;
5684 6559 }
5685
5686 6954 bool Item_func_release_lock::itemize(Parse_context *pc, Item **res) {
5687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6954 times.
6954 if (skip_itemize(res)) return false;
5688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6954 times.
6954 if (super::itemize(pc, res)) return true;
5689 6954 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5690 6954 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5691 6954 return false;
5692 }
5693
5694 /**
5695 Release a user level lock.
5696
5697 @note Sets null_value to true on error/if no connection holds such lock.
5698
5699 @note This means that SQL-function RELEASE_LOCK() returns:
5700 1 - if lock was held by this connection and was released.
5701 0 - if lock was held by some other connection (and was not released).
5702 NULL - if name of lock is bad or if it was not held by any connection
5703 (in the former case also error will be emitted),
5704
5705 @return
5706 - 1 if lock released
5707 - 0 if lock wasn't held/error.
5708 */
5709
5710 6420 longlong Item_func_release_lock::val_int() {
5711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6420 times.
6420 assert(fixed == 1);
5712
1/2
✓ Branch 0 taken 6420 times.
✗ Branch 1 not taken.
6420 String *res = args[0]->val_str(&value);
5713 char name[NAME_LEN + 1];
5714
1/2
✓ Branch 0 taken 6420 times.
✗ Branch 1 not taken.
6420 THD *thd = current_thd;
5715
1/2
✓ Branch 0 taken 6420 times.
✗ Branch 1 not taken.
6420 DBUG_TRACE;
5716
5717 6420 null_value = true;
5718
5719 #ifdef WITH_WSREP
5720 6420 bool block = false;
5721
5722
3/3
✓ Branch 0 taken 6418 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
6420 switch (pxc_strict_mode) {
5723 6418 case PXC_STRICT_MODE_DISABLED:
5724 case PXC_STRICT_MODE_MASTER:
5725 /* Do nothing */
5726 6418 break;
5727 1 case PXC_STRICT_MODE_PERMISSIVE:
5728
10/22
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
1 WSREP_WARN(
5729 "Percona-XtraDB-Cluster doesn't recommend use of"
5730 " RELEASE_LOCK with pxc_strict_mode = PERMISSIVE");
5731
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_UNKNOWN_ERROR,
5732 "Percona-XtraDB-Cluster doesn't recommend use of"
5733 " RELEASE_LOCK with pxc_strict_mode = PERMISSIVE");
5734 1 break;
5735 1 case PXC_STRICT_MODE_ENFORCING:
5736 default:
5737 1 block = true;
5738
13/28
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
1 WSREP_ERROR(
5739 "Percona-XtraDB-Cluster prohibits use of RELEASE_LOCK"
5740 " with pxc_strict_mode = ENFORCING");
5741 char message[1024];
5742 1 sprintf(message,
5743 "Percona-XtraDB-Cluster prohibits use of RELEASE_LOCK"
5744 " with pxc_strict_mode = ENFORCING");
5745
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_message(ER_UNKNOWN_ERROR, message, MYF(0));
5746 1 break;
5747 }
5748
5749
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6419 times.
6420 if (block) return 0;
5750 #endif /* WITH_WSREP */
5751
5752
3/4
✓ Branch 0 taken 6419 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 6415 times.
6419 if (check_and_convert_ull_name(name, res)) return 0;
5753
5754
3/8
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6415 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6415 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
6415 DBUG_PRINT("info", ("lock %s", name));
5755
5756 6415 MDL_key ull_key;
5757
1/2
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
6415 ull_key.mdl_key_init(MDL_key::USER_LEVEL_LOCK, "", name);
5758
5759
1/2
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
6415 const auto it = thd->ull_hash.find(
5760
2/4
✓ Branch 0 taken 6415 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6415 times.
✗ Branch 3 not taken.
12830 std::string(pointer_cast<const char *>(ull_key.ptr()), ull_key.length()));
5761
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6404 times.
6415 if (it == thd->ull_hash.end()) {
5762 /*
5763 When RELEASE_LOCK() is called for lock which is not owned by the
5764 connection it should return 0 or NULL depending on whether lock
5765 is owned by any other connection or not.
5766 */
5767 11 MDL_lock_get_owner_thread_id_visitor get_owner_visitor;
5768
5769
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (thd->mdl_context.find_lock_owner(&ull_key, &get_owner_visitor))
5770 return 0;
5771
5772 11 null_value = get_owner_visitor.get_owner_id() == 0;
5773
5774 11 return 0;
5775 11 }
5776 6404 User_level_lock *ull = it->second;
5777
5778 6404 null_value = false;
5779
2/2
✓ Branch 0 taken 6393 times.
✓ Branch 1 taken 11 times.
6404 if (--ull->refs == 0) {
5780
1/2
✓ Branch 0 taken 6393 times.
✗ Branch 1 not taken.
6393 thd->ull_hash.erase(it);
5781
1/2
✓ Branch 0 taken 6393 times.
✗ Branch 1 not taken.
6393 thd->mdl_context.release_lock(ull->ticket);
5782
1/2
✓ Branch 0 taken 6393 times.
✗ Branch 1 not taken.
6393 my_free(ull);
5783 }
5784 6404 return 1;
5785 6420 }
5786
5787 33 bool Item_func_release_all_locks::itemize(Parse_context *pc, Item **res) {
5788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (skip_itemize(res)) return false;
5789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (super::itemize(pc, res)) return true;
5790 33 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5791 33 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5792 33 return false;
5793 }
5794
5795 /**
5796 Release all user level lock held by connection.
5797
5798 @return Number of locks released including recursive lock count.
5799 */
5800
5801 29 longlong Item_func_release_all_locks::val_int() {
5802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 assert(fixed == 1);
5803
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 THD *thd = current_thd;
5804 29 uint result = 0;
5805
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 DBUG_TRACE;
5806
5807
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 29 times.
54 for (const auto &key_and_value : thd->ull_hash) {
5808 25 User_level_lock *ull = key_and_value.second;
5809
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 thd->mdl_context.release_lock(ull->ticket);
5810 25 result += ull->refs;
5811
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 my_free(ull);
5812 }
5813 29 thd->ull_hash.clear();
5814
5815 29 return result;
5816 29 }
5817
5818 68 bool Item_func_is_free_lock::itemize(Parse_context *pc, Item **res) {
5819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (skip_itemize(res)) return false;
5820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (super::itemize(pc, res)) return true;
5821 68 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5822 68 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5823 68 return false;
5824 }
5825
5826 /**
5827 Check if user level lock is free.
5828
5829 @note Sets null_value=true on error.
5830
5831 @note As result SQL-function IS_FREE_LOCK() returns:
5832 1 - if lock is free,
5833 0 - if lock is in use
5834 NULL - if lock name is bad or OOM (also error is emitted).
5835
5836 @retval
5837 1 Available
5838 @retval
5839 0 Already taken, or error
5840 */
5841
5842 62 longlong Item_func_is_free_lock::val_int() {
5843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 assert(fixed == 1);
5844 62 value.length(0);
5845
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 String *res = args[0]->val_str(&value);
5846 char name[NAME_LEN + 1];
5847
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 THD *thd = current_thd;
5848
5849 62 null_value = true;
5850
5851
3/4
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 58 times.
62 if (check_and_convert_ull_name(name, res)) return 0;
5852
5853 58 MDL_key ull_key;
5854
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 ull_key.mdl_key_init(MDL_key::USER_LEVEL_LOCK, "", name);
5855
5856 58 MDL_lock_get_owner_thread_id_visitor get_owner_visitor;
5857
5858
2/4
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 58 times.
58 if (thd->mdl_context.find_lock_owner(&ull_key, &get_owner_visitor)) return 0;
5859
5860 58 null_value = false;
5861 58 return (get_owner_visitor.get_owner_id() == 0);
5862 58 }
5863
5864 586 bool Item_func_is_used_lock::itemize(Parse_context *pc, Item **res) {
5865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 586 times.
586 if (skip_itemize(res)) return false;
5866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 586 times.
586 if (super::itemize(pc, res)) return true;
5867 586 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5868 586 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5869 586 return false;
5870 }
5871
5872 /**
5873 Check if user level lock is used and return connection id of owner.
5874
5875 @note Sets null_value=true if lock is free/on error.
5876
5877 @note SQL-function IS_USED_LOCK() returns:
5878 # - connection id of lock owner if lock is acquired.
5879 NULL - if lock is free or on error (in the latter case
5880 also error is emitted).
5881
5882 @return Connection id of lock owner, 0 if lock is free/on error.
5883 */
5884
5885 59 longlong Item_func_is_used_lock::val_int() {
5886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 assert(fixed == 1);
5887
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 String *res = args[0]->val_str(&value);
5888 char name[NAME_LEN + 1];
5889
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 THD *thd = current_thd;
5890
5891 59 null_value = true;
5892
5893
3/4
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 56 times.
59 if (check_and_convert_ull_name(name, res)) return 0;
5894
5895 56 MDL_key ull_key;
5896
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 ull_key.mdl_key_init(MDL_key::USER_LEVEL_LOCK, "", name);
5897
5898 56 MDL_lock_get_owner_thread_id_visitor get_owner_visitor;
5899
5900
2/4
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 56 times.
56 if (thd->mdl_context.find_lock_owner(&ull_key, &get_owner_visitor)) return 0;
5901
5902 56 my_thread_id thread_id = get_owner_visitor.get_owner_id();
5903
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 32 times.
56 if (thread_id == 0) return 0;
5904
5905 32 null_value = false;
5906 32 return thread_id;
5907 56 }
5908
5909 1389 bool Item_func_last_insert_id::itemize(Parse_context *pc, Item **res) {
5910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1389 times.
1389 if (skip_itemize(res)) return false;
5911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1389 times.
1389 if (super::itemize(pc, res)) return true;
5912 1389 pc->thd->lex->safe_to_cache_query = false;
5913 1389 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5914 1389 return false;
5915 }
5916
5917 1862 longlong Item_func_last_insert_id::val_int() {
5918 1862 THD *thd = current_thd;
5919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1862 times.
1862 assert(fixed == 1);
5920
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1842 times.
1862 if (arg_count) {
5921 20 longlong value = args[0]->val_int();
5922 20 null_value = args[0]->null_value;
5923 /*
5924 LAST_INSERT_ID(X) must affect the client's mysql_insert_id() as
5925 documented in the manual. We don't want to touch
5926 first_successful_insert_id_in_cur_stmt because it would make
5927 LAST_INSERT_ID(X) take precedence over an generated auto_increment
5928 value for this row.
5929 */
5930 20 thd->arg_of_last_insert_id_function = true;
5931 20 thd->first_successful_insert_id_in_prev_stmt = value;
5932 20 return value;
5933 }
5934 return static_cast<longlong>(
5935 1842 thd->read_first_successful_insert_id_in_prev_stmt());
5936 }
5937
5938 52 bool Item_func_benchmark::itemize(Parse_context *pc, Item **res) {
5939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (skip_itemize(res)) return false;
5940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (super::itemize(pc, res)) return true;
5941 52 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5942 52 return false;
5943 }
5944
5945 /* This function is just used to test speed of different functions */
5946
5947 32 longlong Item_func_benchmark::val_int() {
5948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 assert(fixed == 1);
5949 char buff[MAX_FIELD_WIDTH];
5950 32 String tmp(buff, sizeof(buff), &my_charset_bin);
5951 32 my_decimal tmp_decimal;
5952
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 THD *thd = current_thd;
5953 ulonglong loop_count;
5954
5955
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 loop_count = (ulonglong)args[0]->val_int();
5956
5957
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 2 times.
32 if (args[0]->null_value ||
5958
3/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 29 times.
30 (!args[0]->unsigned_flag && (((longlong)loop_count) < 0))) {
5959
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!args[0]->null_value) {
5960 char errbuff[22];
5961
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 llstr(((longlong)loop_count), errbuff);
5962
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 push_warning_printf(current_thd, Sql_condition::SL_WARNING,
5963 ER_WRONG_VALUE_FOR_TYPE,
5964
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ER_THD(current_thd, ER_WRONG_VALUE_FOR_TYPE), "count",
5965 errbuff, "benchmark");
5966 }
5967
5968 3 null_value = true;
5969 3 return 0;
5970 }
5971
5972 29 null_value = false;
5973
5/6
✓ Branch 0 taken 1440 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 1440 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1440 times.
✓ Branch 5 taken 29 times.
1469 for (ulonglong loop = 0; loop < loop_count && !thd->killed; loop++) {
5974
5/7
✓ Branch 0 taken 1440 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 1000 times.
✓ Branch 4 taken 100 times.
✓ Branch 5 taken 300 times.
✗ Branch 6 not taken.
1440 switch (args[1]->result_type()) {
5975 40 case REAL_RESULT:
5976
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 (void)args[1]->val_real();
5977 40 break;
5978 1000 case INT_RESULT:
5979
1/2
✓ Branch 0 taken 1000 times.
✗ Branch 1 not taken.
1000 (void)args[1]->val_int();
5980 1000 break;
5981 100 case STRING_RESULT:
5982
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 (void)args[1]->val_str(&tmp);
5983 100 break;
5984 300 case DECIMAL_RESULT:
5985
1/2
✓ Branch 0 taken 300 times.
✗ Branch 1 not taken.
300 (void)args[1]->val_decimal(&tmp_decimal);
5986 300 break;
5987 case ROW_RESULT:
5988 default:
5989 // This case should never be chosen
5990 assert(0);
5991 return 0;
5992 }
5993 }
5994 29 return 0;
5995 32 }
5996
5997 19 void Item_func_benchmark::print(const THD *thd, String *str,
5998 enum_query_type query_type) const {
5999 19 str->append(STRING_WITH_LEN("benchmark("));
6000 19 args[0]->print(thd, str, query_type);
6001 19 str->append(',');
6002 19 args[1]->print(thd, str, query_type);
6003 19 str->append(')');
6004 19 }
6005
6006 /**
6007 Lock which is used to implement interruptible wait for SLEEP() function.
6008 */
6009
6010 mysql_mutex_t LOCK_item_func_sleep;
6011
6012 #ifdef HAVE_PSI_INTERFACE
6013 static PSI_mutex_key key_LOCK_item_func_sleep;
6014
6015 static PSI_mutex_info item_func_sleep_mutexes[] = {
6016 {&key_LOCK_item_func_sleep, "LOCK_item_func_sleep", PSI_FLAG_SINGLETON, 0,
6017 PSI_DOCUMENT_ME}};
6018
6019 9786 static void init_item_func_sleep_psi_keys() {
6020 int count;
6021
6022 9786 count = static_cast<int>(array_elements(item_func_sleep_mutexes));
6023 9786 mysql_mutex_register("sql", item_func_sleep_mutexes, count);
6024 9786 }
6025 #endif
6026
6027 static bool item_func_sleep_inited = false;
6028
6029 9786 void item_func_sleep_init() {
6030 #ifdef HAVE_PSI_INTERFACE
6031 9786 init_item_func_sleep_psi_keys();
6032 #endif
6033
6034 9786 mysql_mutex_init(key_LOCK_item_func_sleep, &LOCK_item_func_sleep,
6035 MY_MUTEX_INIT_SLOW);
6036 9786 item_func_sleep_inited = true;
6037 9786 }
6038
6039 8468 void item_func_sleep_free() {
6040
2/2
✓ Branch 0 taken 8430 times.
✓ Branch 1 taken 38 times.
8468 if (item_func_sleep_inited) {
6041 8430 item_func_sleep_inited = false;
6042 8430 mysql_mutex_destroy(&LOCK_item_func_sleep);
6043 }
6044 8468 }
6045
6046 7721 bool Item_func_sleep::itemize(Parse_context *pc, Item **res) {
6047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7722 times.
7721 if (skip_itemize(res)) return false;
6048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7723 times.
7722 if (super::itemize(pc, res)) return true;
6049 7723 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
6050 7723 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
6051 7723 return false;
6052 }
6053
6054 /** This function is just used to create tests with time gaps. */
6055
6056 10696 longlong Item_func_sleep::val_int() {
6057
1/2
✓ Branch 0 taken 10697 times.
✗ Branch 1 not taken.
10696 THD *thd = current_thd;
6058 10697 Interruptible_wait timed_cond(thd);
6059 mysql_cond_t cond;
6060 double timeout;
6061 int error;
6062
6063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10696 times.
10696 assert(fixed == 1);
6064
6065
1/2
✓ Branch 0 taken 10697 times.
✗ Branch 1 not taken.
10696 timeout = args[0]->val_real();
6066
6067 /*
6068 Report error or warning depending on the value of SQL_MODE.
6069 If SQL is STRICT then report error, else report warning and continue
6070 execution.
6071 */
6072
6073
3/4
✓ Branch 0 taken 10695 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10695 times.
10697 if (args[0]->null_value || timeout < 0) {
6074
5/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 if (!thd->lex->is_ignore() && thd->is_strict_mode()) {
6075
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_WRONG_ARGUMENTS, MYF(0), "sleep.");
6076 1 return 0;
6077 } else
6078
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
6079 ER_THD(thd, ER_WRONG_ARGUMENTS), "sleep.");
6080 }
6081 /*
6082 On 64-bit OSX mysql_cond_timedwait() waits forever
6083 if passed abstime time has already been exceeded by
6084 the system time.
6085 When given a very short timeout (< 10 mcs) just return
6086 immediately.
6087 We assume that the lines between this test and the call
6088 to mysql_cond_timedwait() will be executed in less than 0.00001 sec.
6089 */
6090
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 10683 times.
10696 if (timeout < 0.00001) return 0;
6091
6092
1/2
✓ Branch 0 taken 10683 times.
✗ Branch 1 not taken.
10683 timed_cond.set_timeout((ulonglong)(timeout * 1000000000.0));
6093
6094
1/2
✓ Branch 0 taken 10683 times.
✗ Branch 1 not taken.
10683 mysql_cond_init(key_item_func_sleep_cond, &cond);
6095
1/2
✓ Branch 0 taken 10683 times.
✗ Branch 1 not taken.
10683 mysql_mutex_lock(&LOCK_item_func_sleep);
6096
6097
1/2
✓ Branch 0 taken 10683 times.
✗ Branch 1 not taken.
10683 thd->ENTER_COND(&cond, &LOCK_item_func_sleep, &stage_user_sleep, nullptr);
6098
6099
3/6
✓ Branch 0 taken 10683 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10683 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10683 times.
✗ Branch 5 not taken.
10683 DEBUG_SYNC(current_thd, "func_sleep_before_sleep");
6100
6101 10683 error = 0;
6102
1/2
✓ Branch 0 taken 10683 times.
✗ Branch 1 not taken.
10683 thd_wait_begin(thd, THD_WAIT_SLEEP);
6103
2/2
✓ Branch 0 taken 10683 times.
✓ Branch 1 taken 32 times.
10715 while (!thd->killed) {
6104
1/2
✓ Branch 0 taken 10654 times.
✗ Branch 1 not taken.
10683 error = timed_cond.wait(&cond, &LOCK_item_func_sleep);
6105
2/2
✓ Branch 0 taken 10622 times.
✓ Branch 1 taken 32 times.
10654 if (is_timeout(error)) break;
6106 32 error = 0;
6107 }
6108
1/2
✓ Branch 0 taken 10654 times.
✗ Branch 1 not taken.
10654 thd_wait_end(thd);
6109
1/2
✓ Branch 0 taken 10654 times.
✗ Branch 1 not taken.
10654 mysql_mutex_unlock(&LOCK_item_func_sleep);
6110
1/2
✓ Branch 0 taken 10654 times.
✗ Branch 1 not taken.
10654 thd->EXIT_COND(nullptr);
6111
6112
1/2
✓ Branch 0 taken 10654 times.
✗ Branch 1 not taken.
10654 mysql_cond_destroy(&cond);
6113
6114 10654 return (error == 0); // Return 1 killed
6115 }
6116
6117 /**
6118 Get variable with given name; conditionally create it if non-existing
6119
6120 @param thd thread context
6121 @param name name of user variable
6122 @param cs character set;
6123 = NULL: Do not create variable if non-existing.
6124 != NULL: Create variable with this character set.
6125
6126 @returns pointer to variable entry.
6127 = NULL: variable does not exist (if cs == NULL), or
6128 could not create variable (if cs != NULL)
6129 */
6130 3440377 static user_var_entry *get_variable(THD *thd, const Name_string &name,
6131 const CHARSET_INFO *cs) {
6132
1/2
✓ Branch 0 taken 3440428 times.
✗ Branch 1 not taken.
3440377 const std::string key(name.ptr(), name.length());
6133
6134 /* Protects thd->user_vars. */
6135 mysql_mutex_assert_owner(&thd->LOCK_thd_data);
6136
6137
1/2
✓ Branch 0 taken 3440448 times.
✗ Branch 1 not taken.
3440437 user_var_entry *entry = find_or_nullptr(thd->user_vars, key);
6138
4/4
✓ Branch 0 taken 161838 times.
✓ Branch 1 taken 3278610 times.
✓ Branch 2 taken 145303 times.
✓ Branch 3 taken 16535 times.
3440448 if (entry == nullptr && cs != nullptr) {
6139
1/2
✓ Branch 0 taken 145303 times.
✗ Branch 1 not taken.
145303 entry = user_var_entry::create(thd, name, cs);
6140
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 145300 times.
145303 if (entry == nullptr) return nullptr;
6141
1/2
✓ Branch 0 taken 145300 times.
✗ Branch 1 not taken.
145300 thd->user_vars.emplace(
6142 290600 key, unique_ptr_with_deleter<user_var_entry>(entry, &free_user_var));
6143 }
6144 3440445 return entry;
6145 3440448 }
6146
6147 850642 void Item_func_set_user_var::cleanup() {
6148 850642 Item_func::cleanup();
6149 /*
6150 Ensure that a valid user variable object is rebound on next
6151 execution. This is important if the user variable is referenced by a
6152 trigger: the trigger references an Item_func_set_user_var, and may be
6153 used by another THD in the future (the trigger is cached in a TABLE). When
6154 that later happens, the other THD will use the same Item_func_set_user_var
6155 but shouldn't try to access the previous THD's entry. So we clear it here,
6156 and set it again later in Item_func_set_user_var::update().
6157 */
6158 850673 entry = nullptr;
6159 850673 }
6160
6161 1383863 bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists) {
6162
2/2
✓ Branch 0 taken 1380762 times.
✓ Branch 1 taken 3101 times.
1383863 if (entry == nullptr) {
6163 const CHARSET_INFO *cs =
6164 create_if_not_exists
6165
2/2
✓ Branch 0 taken 1375333 times.
✓ Branch 1 taken 5429 times.
2756111 ? (args[0]->collation.derivation == DERIVATION_NUMERIC
6166
2/2
✓ Branch 0 taken 872666 times.
✓ Branch 1 taken 502667 times.
1375333 ? default_charset()
6167 502667 : args[0]->collation.collation)
6168 1380778 : nullptr;
6169
6170 /* Protects thd->user_vars. */
6171 1380778 mysql_mutex_lock(&thd->LOCK_thd_data);
6172 1380757 entry = get_variable(thd, name, cs);
6173 1380785 mysql_mutex_unlock(&thd->LOCK_thd_data);
6174
6175
2/2
✓ Branch 0 taken 451 times.
✓ Branch 1 taken 1380358 times.
1380809 if (entry == nullptr) return true;
6176 }
6177
6178 // Ensure this user variable is owned by the current session
6179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1383413 times.
1383459 assert(entry->owner_session() == thd);
6180
6181 1383413 return false;
6182 }
6183
6184 /*
6185 When a user variable is updated (in a SET command or a query like
6186 SELECT @a:= ).
6187 */
6188
6189 531727 bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref) {
6190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 531727 times.
531727 assert(!fixed);
6191
6192
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 531507 times.
531727 if (Item_func::fix_fields(thd, ref)) return true;
6193
6194 // This is probably only to get an early validity check on user variable name
6195
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 531503 times.
531507 if (set_entry(thd, true)) return true;
6196 531503 entry = nullptr;
6197
6198 531503 null_item = (args[0]->type() == NULL_ITEM);
6199
6200 531503 return false;
6201 }
6202
6203 531504 bool Item_func_set_user_var::resolve_type(THD *thd) {
6204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 531507 times.
531504 if (Item_var_func::resolve_type(thd)) return true;
6205 531507 set_nullable(args[0]->is_nullable());
6206 531507 collation.set(DERIVATION_IMPLICIT);
6207 /*
6208 this sets the character set of the item immediately; rules for the
6209 character set of the variable ("entry" object) are different: if "entry"
6210 did not exist previously, set_entry () has created it and has set its
6211 character set; but if it existed previously, it keeps its previous
6212 character set, which may change only when we are sure that the assignment
6213 is to be executed, i.e. in user_var_entry::store ().
6214 */
6215
2/2
✓ Branch 0 taken 322646 times.
✓ Branch 1 taken 208861 times.
531507 if (args[0]->collation.derivation == DERIVATION_NUMERIC)
6216 322646 collation.collation = default_charset();
6217 else
6218 208861 collation.collation = args[0]->collation.collation;
6219
6220 531507 enum_field_types type = Item::type_for_variable(args[0]->data_type());
6221
4/5
✓ Branch 0 taken 304010 times.
✓ Branch 1 taken 3322 times.
✓ Branch 2 taken 15138 times.
✓ Branch 3 taken 209035 times.
✗ Branch 4 not taken.
531505 switch (type) {
6222 304010 case MYSQL_TYPE_LONGLONG:
6223 304010 set_data_type_longlong();
6224 304009 unsigned_flag = args[0]->unsigned_flag;
6225 304009 max_length =
6226 304009 args[0]->max_length; // Preserves "length" of integer constants
6227 304009 break;
6228 3322 case MYSQL_TYPE_NEWDECIMAL:
6229 3322 set_data_type_decimal(args[0]->decimal_precision(), args[0]->decimals);
6230 3322 break;
6231 15138 case MYSQL_TYPE_DOUBLE:
6232 15138 set_data_type_double();
6233 15138 break;
6234 209035 case MYSQL_TYPE_VARCHAR:
6235 209035 set_data_type_string(args[0]->max_char_length());
6236 209035 break;
6237 case MYSQL_TYPE_NULL:
6238 default:
6239 assert(false);
6240 set_data_type(MYSQL_TYPE_NULL);
6241 break;
6242 }
6243
6244 531504 cached_result_type = Item::type_to_result(data_type());
6245
6246 531505 return false;
6247 }
6248
6249 // static
6250 145303 user_var_entry *user_var_entry::create(THD *thd, const Name_string &name,
6251 const CHARSET_INFO *cs) {
6252
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 145300 times.
145303 if (check_column_name(name.ptr())) {
6253 3 my_error(ER_ILLEGAL_USER_VAR, MYF(0), name.ptr());
6254 3 return nullptr;
6255 }
6256
6257 user_var_entry *entry;
6258 size_t size =
6259 145300 ALIGN_SIZE(sizeof(user_var_entry)) + (name.length() + 1) + extra_size;
6260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145300 times.
145300 if (!(entry = (user_var_entry *)my_malloc(key_memory_user_var_entry, size,
6261 MYF(MY_WME | ME_FATALERROR))))
6262 return nullptr;
6263 145300 entry->init(thd, name, cs);
6264 145300 return entry;
6265 }
6266
6267 4068343 bool user_var_entry::mem_realloc(size_t length) {
6268
2/2
✓ Branch 0 taken 3741656 times.
✓ Branch 1 taken 326687 times.
4068343 if (length <= extra_size) {
6269 /* Enough space to store value in value struct */
6270 3741656 free_value();
6271 3741690 m_ptr = internal_buffer_ptr();
6272 } else {
6273 /* Allocate an external buffer */
6274
2/2
✓ Branch 0 taken 322350 times.
✓ Branch 1 taken 4337 times.
326687 if (m_length != length) {
6275
2/2
✓ Branch 0 taken 10643 times.
✓ Branch 1 taken 311711 times.
322350 if (m_ptr == internal_buffer_ptr()) m_ptr = nullptr;
6276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 322354 times.
322354 if (!(m_ptr = (char *)my_realloc(
6277 322354 key_memory_user_var_entry_value, m_ptr, length,
6278 MYF(MY_ALLOW_ZERO_PTR | MY_WME | ME_FATALERROR))))
6279 return true;
6280 }
6281 }
6282 4068400 return false;
6283 }
6284
6285 145300 void user_var_entry::init(THD *thd, const Simple_cstring &name,
6286 const CHARSET_INFO *cs) {
6287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145300 times.
145300 assert(thd != nullptr);
6288 145300 m_owner = thd;
6289 145300 copy_name(name);
6290 145300 reset_value();
6291 145300 m_used_query_id = 0;
6292 145300 collation.set(cs, DERIVATION_IMPLICIT, 0);
6293 145300 unsigned_flag = false;
6294 145300 m_type = STRING_RESULT;
6295 145300 }
6296
6297 4068347 bool user_var_entry::store(const void *from, size_t length, Item_result type) {
6298 4068347 assert_locked();
6299
6300 // Store strings with end \0
6301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4068400 times.
4068376 if (mem_realloc(length + (type == STRING_RESULT))) return true;
6302
2/2
✓ Branch 0 taken 372782 times.
✓ Branch 1 taken 3695618 times.
4068400 if (type == STRING_RESULT) m_ptr[length] = 0; // Store end \0
6303
6304 // Avoid memcpy of a my_decimal object, use copy CTOR instead.
6305
2/2
✓ Branch 0 taken 2663 times.
✓ Branch 1 taken 4065737 times.
4068400 if (type == DECIMAL_RESULT) {
6306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2663 times.
2663 assert(length == sizeof(my_decimal));
6307 2663 const my_decimal *dec = static_cast<const my_decimal *>(from);
6308 2663 dec->sanity_check();
6309
1/2
✓ Branch 0 taken 2663 times.
✗ Branch 1 not taken.
2663 new (m_ptr) my_decimal(*dec);
6310 } else
6311 4065737 memcpy(m_ptr, from, length);
6312
6313 4068400 m_length = length;
6314 4068400 m_type = type;
6315
6316 4068400 set_used_query_id(current_thd->query_id);
6317
6318 4068378 return false;
6319 }
6320
6321 8285064 void user_var_entry::assert_locked() const {
6322 mysql_mutex_assert_owner(&m_owner->LOCK_thd_data);
6323 8285064 }
6324
6325 4068351 bool user_var_entry::store(const void *ptr, size_t length, Item_result type,
6326 const CHARSET_INFO *cs, Derivation dv,
6327 bool unsigned_arg) {
6328 4068351 assert_locked();
6329
6330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4068381 times.
4068402 if (store(ptr, length, type)) return true;
6331 4068381 collation.set(cs, dv);
6332 4068357 unsigned_flag = unsigned_arg;
6333 4068357 return false;
6334 }
6335
6336 4071722 void user_var_entry::lock() {
6337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4071722 times.
4071722 assert(m_owner != nullptr);
6338 4071722 mysql_mutex_lock(&m_owner->LOCK_thd_data);
6339 4071740 }
6340
6341 4071716 void user_var_entry::unlock() {
6342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4071716 times.
4071716 assert(m_owner != nullptr);
6343 4071716 mysql_mutex_unlock(&m_owner->LOCK_thd_data);
6344 4071783 }
6345
6346 4070859 bool Item_func_set_user_var::update_hash(const void *ptr, uint length,
6347 Item_result res_type,
6348 const CHARSET_INFO *cs, Derivation dv,
6349 bool unsigned_arg) {
6350 4070859 entry->lock();
6351
6352 // args[0]->null_value could be outdated
6353
2/2
✓ Branch 0 taken 23025 times.
✓ Branch 1 taken 4047813 times.
4070877 if (args[0]->type() == Item::FIELD_ITEM)
6354 23025 null_value = ((Item_field *)args[0])->field->is_null();
6355 else
6356 4047813 null_value = args[0]->null_value;
6357
6358
2/2
✓ Branch 0 taken 2516 times.
✓ Branch 1 taken 4068322 times.
4070838 if (ptr == nullptr) {
6359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2516 times.
2516 assert(length == 0);
6360 2516 null_value = true;
6361 }
6362
6363 /*
6364 If we set a variable explicitly to NULL then keep the old
6365 result type of the variable
6366 */
6367
4/4
✓ Branch 0 taken 3326 times.
✓ Branch 1 taken 4067512 times.
✓ Branch 2 taken 857 times.
✓ Branch 3 taken 2469 times.
4070838 if (null_value && null_item) res_type = entry->type();
6368
6369
2/2
✓ Branch 0 taken 3325 times.
✓ Branch 1 taken 4067514 times.
4070839 if (null_value)
6370 3325 entry->set_null_value(res_type);
6371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4067525 times.
4067514 else if (entry->store(ptr, length, res_type, cs, dv, unsigned_arg)) {
6372 entry->unlock();
6373 null_value = true;
6374 return true;
6375 }
6376 4070851 entry->unlock();
6377 4070919 return false;
6378 }
6379
6380 /** Get the value of a variable as a double. */
6381
6382 581428 double user_var_entry::val_real(bool *null_value) const {
6383
2/2
✓ Branch 0 taken 206 times.
✓ Branch 1 taken 581222 times.
581428 if ((*null_value = (m_ptr == nullptr))) return 0.0;
6384
6385
4/6
✓ Branch 0 taken 85699 times.
✓ Branch 1 taken 491738 times.
✓ Branch 2 taken 1164 times.
✓ Branch 3 taken 2621 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
581222 switch (m_type) {
6386 85699 case REAL_RESULT:
6387 85699 return *reinterpret_cast<double *>(m_ptr);
6388 491738 case INT_RESULT:
6389
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 491730 times.
491738 if (unsigned_flag)
6390 8 return static_cast<double>(*reinterpret_cast<ulonglong *>(m_ptr));
6391 else
6392 491730 return static_cast<double>(*reinterpret_cast<longlong *>(m_ptr));
6393 1164 case DECIMAL_RESULT: {
6394 double result;
6395
1/2
✓ Branch 0 taken 1164 times.
✗ Branch 1 not taken.
1164 my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)m_ptr, &result);
6396 1164 return result;
6397 }
6398 2621 case STRING_RESULT:
6399 5242 return double_from_string_with_check(collation.collation, m_ptr,
6400 2621 m_ptr + m_length);
6401 case ROW_RESULT:
6402 case INVALID_RESULT:
6403 assert(false); // Impossible
6404 break;
6405 }
6406 return 0.0; // Impossible
6407 }
6408
6409 /** Get the value of a variable as an integer. */
6410
6411 11418788 longlong user_var_entry::val_int(bool *null_value) const {
6412
2/2
✓ Branch 0 taken 1073 times.
✓ Branch 1 taken 11417715 times.
11418788 if ((*null_value = (m_ptr == nullptr))) return 0LL;
6413
6414
4/6
✓ Branch 0 taken 112076 times.
✓ Branch 1 taken 11301484 times.
✓ Branch 2 taken 4089 times.
✓ Branch 3 taken 70 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
11417715 switch (m_type) {
6415 112076 case REAL_RESULT: {
6416 // TODO(tdidriks): Consider reporting a possible overflow warning.
6417 112076 double var_val = *(reinterpret_cast<double *>(m_ptr));
6418 longlong res;
6419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112076 times.
112076 if (var_val <= LLONG_MIN) {
6420 res = LLONG_MIN;
6421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112076 times.
112076 } else if (var_val >= LLONG_MAX_DOUBLE) {
6422 res = LLONG_MAX;
6423 } else
6424 112076 res = var_val;
6425
6426 112076 return res;
6427 }
6428 11301484 case INT_RESULT:
6429 11301484 return *(longlong *)m_ptr;
6430 4089 case DECIMAL_RESULT: {
6431 longlong result;
6432
1/2
✓ Branch 0 taken 4089 times.
✗ Branch 1 not taken.
4089 my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)m_ptr, false, &result);
6433 4089 return result;
6434 }
6435 70 case STRING_RESULT: {
6436 int error;
6437
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 return my_strtoll10(m_ptr, nullptr,
6438 70 &error); // String is null terminated
6439 }
6440 case ROW_RESULT:
6441 case INVALID_RESULT:
6442 assert(false); // Impossible
6443 break;
6444 }
6445 return 0LL; // Impossible
6446 }
6447
6448 /** Get the value of a variable as a string. */
6449
6450 1953354 String *user_var_entry::val_str(bool *null_value, String *str,
6451 uint decimals) const {
6452
2/2
✓ Branch 0 taken 4078 times.
✓ Branch 1 taken 1949276 times.
1953354 if ((*null_value = (m_ptr == nullptr))) return (String *)nullptr;
6453
6454
4/6
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 81155 times.
✓ Branch 2 taken 267 times.
✓ Branch 3 taken 1867797 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1949276 switch (m_type) {
6455 63 case REAL_RESULT:
6456 63 str->set_real(*(double *)m_ptr, decimals, collation.collation);
6457 63 break;
6458 81155 case INT_RESULT:
6459
2/2
✓ Branch 0 taken 80930 times.
✓ Branch 1 taken 225 times.
81155 if (!unsigned_flag)
6460 80930 str->set(*(longlong *)m_ptr, collation.collation);
6461 else
6462 225 str->set(*(ulonglong *)m_ptr, collation.collation);
6463 81154 break;
6464 267 case DECIMAL_RESULT:
6465 267 str_set_decimal(E_DEC_FATAL_ERROR, pointer_cast<my_decimal *>(m_ptr), str,
6466 267 collation.collation, decimals);
6467 271 break;
6468 1867797 case STRING_RESULT:
6469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1867801 times.
1867797 if (str->copy(m_ptr, m_length, collation.collation))
6470 str = nullptr; // EOM error
6471 1867801 break;
6472 case ROW_RESULT:
6473 case INVALID_RESULT:
6474 assert(false); // Impossible
6475 break;
6476 }
6477 1949283 return (str);
6478 }
6479
6480 /** Get the value of a variable as a decimal. */
6481
6482 181847 my_decimal *user_var_entry::val_decimal(bool *null_value,
6483 my_decimal *val) const {
6484
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 181706 times.
181847 if ((*null_value = (m_ptr == nullptr))) return nullptr;
6485
6486
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 180041 times.
✓ Branch 2 taken 1659 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
181706 switch (m_type) {
6487 1 case REAL_RESULT:
6488 1 double2my_decimal(E_DEC_FATAL_ERROR, *(double *)m_ptr, val);
6489 1 break;
6490 180041 case INT_RESULT:
6491 180041 int2my_decimal(E_DEC_FATAL_ERROR, *pointer_cast<longlong *>(m_ptr),
6492 180041 unsigned_flag, val);
6493 180041 break;
6494 1659 case DECIMAL_RESULT:
6495 1659 my_decimal2decimal(reinterpret_cast<my_decimal *>(m_ptr), val);
6496 1659 break;
6497 5 case STRING_RESULT:
6498 5 str2my_decimal(E_DEC_FATAL_ERROR, m_ptr, m_length, collation.collation,
6499 val);
6500 5 break;
6501 case ROW_RESULT:
6502 case INVALID_RESULT:
6503 assert(false); // Impossible
6504 break;
6505 }
6506 181706 return (val);
6507 }
6508
6509 /**
6510 This functions is invoked on SET \@variable or
6511 \@variable:= expression.
6512
6513 Evaluate (and check expression), store results.
6514
6515 @note
6516 For now it always return OK. All problem with value evaluating
6517 will be caught by thd->is_error() check in sql_set_variables().
6518
6519 @retval
6520 false OK.
6521 */
6522
6523 3956695 bool Item_func_set_user_var::check(bool use_result_field) {
6524
1/2
✓ Branch 0 taken 3956758 times.
✗ Branch 1 not taken.
3956695 DBUG_TRACE;
6525
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 3956729 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
3956758 if (use_result_field && !result_field) use_result_field = false;
6526
6527
5/5
✓ Branch 0 taken 93351 times.
✓ Branch 1 taken 3498508 times.
✓ Branch 2 taken 362426 times.
✓ Branch 3 taken 2451 times.
✓ Branch 4 taken 22 times.
3956758 switch (cached_result_type) {
6528 93351 case REAL_RESULT: {
6529 93351 save_result.vreal =
6530
4/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 93347 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 93347 times.
✗ Branch 5 not taken.
93351 use_result_field ? result_field->val_real() : args[0]->val_real();
6531 93351 break;
6532 }
6533 3498508 case INT_RESULT: {
6534 3498489 save_result.vint =
6535
4/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3498495 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3498476 times.
✗ Branch 5 not taken.
3498508 use_result_field ? result_field->val_int() : args[0]->val_int();
6536
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3498476 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
3498489 unsigned_flag = use_result_field ? result_field->is_unsigned()
6537 3498476 : args[0]->unsigned_flag;
6538 3498489 break;
6539 }
6540 362426 case STRING_RESULT: {
6541
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 362418 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
362426 save_result.vstr = use_result_field ? result_field->val_str(&value)
6542
1/2
✓ Branch 0 taken 362417 times.
✗ Branch 1 not taken.
362418 : args[0]->val_str(&value);
6543 362425 break;
6544 }
6545 2451 case DECIMAL_RESULT: {
6546 2451 save_result.vdec = use_result_field
6547
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2447 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
2451 ? result_field->val_decimal(&decimal_buff)
6548
1/2
✓ Branch 0 taken 2447 times.
✗ Branch 1 not taken.
2447 : args[0]->val_decimal(&decimal_buff);
6549 2451 break;
6550 }
6551 22 case ROW_RESULT:
6552 default:
6553 // This case should never be chosen
6554 22 assert(0);
6555 break;
6556 }
6557 3956731 return false;
6558 3956716 }
6559
6560 /**
6561 @brief Evaluate and store item's result.
6562 This function is invoked on "SELECT ... INTO @var ...".
6563
6564 @param item An item to get value from.
6565 */
6566
6567 107288 void Item_func_set_user_var::save_item_result(Item *item) {
6568
1/2
✓ Branch 0 taken 107289 times.
✗ Branch 1 not taken.
107288 DBUG_TRACE;
6569
6570
4/5
✓ Branch 0 taken 11660 times.
✓ Branch 1 taken 88148 times.
✓ Branch 2 taken 6372 times.
✓ Branch 3 taken 1109 times.
✗ Branch 4 not taken.
107289 switch (cached_result_type) {
6571 11660 case REAL_RESULT:
6572
1/2
✓ Branch 0 taken 11659 times.
✗ Branch 1 not taken.
11660 save_result.vreal = item->val_real();
6573 11659 break;
6574 88148 case INT_RESULT:
6575
1/2
✓ Branch 0 taken 88148 times.
✗ Branch 1 not taken.
88148 save_result.vint = item->val_int();
6576 88148 unsigned_flag = item->unsigned_flag;
6577 88148 break;
6578 6372 case STRING_RESULT:
6579
1/2
✓ Branch 0 taken 6372 times.
✗ Branch 1 not taken.
6372 save_result.vstr = item->val_str(&value);
6580 6372 break;
6581 1109 case DECIMAL_RESULT:
6582
1/2
✓ Branch 0 taken 1109 times.
✗ Branch 1 not taken.
1109 save_result.vdec = item->val_decimal(&decimal_buff);
6583 1109 break;
6584 case ROW_RESULT:
6585 default:
6586 // Should never happen
6587 assert(0);
6588 break;
6589 }
6590 107288 }
6591
6592 /**
6593 Update user variable from value in save_result
6594
6595 @returns false if success, true when error (EOM)
6596 */
6597
6598 4063947 bool Item_func_set_user_var::update() {
6599
1/2
✓ Branch 0 taken 4063998 times.
✗ Branch 1 not taken.
4063947 DBUG_TRACE;
6600
6601 // Ensure that a user variable object is bound for each execution.
6602
6/10
✓ Branch 0 taken 840047 times.
✓ Branch 1 taken 3223951 times.
✓ Branch 2 taken 840043 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 840017 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 840017 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4063968 times.
4063998 if (entry == nullptr && set_entry(current_thd, true)) return true;
6603
6604 4063968 bool res = false;
6605
6606
4/5
✓ Branch 0 taken 105010 times.
✓ Branch 1 taken 3586642 times.
✓ Branch 2 taken 368765 times.
✓ Branch 3 taken 3560 times.
✗ Branch 4 not taken.
4063968 switch (cached_result_type) {
6607 105010 case REAL_RESULT: {
6608
2/4
✓ Branch 0 taken 105010 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 105010 times.
✗ Branch 3 not taken.
105010 res = update_hash(&save_result.vreal, sizeof(save_result.vreal),
6609 REAL_RESULT, default_charset(), DERIVATION_IMPLICIT,
6610 false);
6611 105010 break;
6612 }
6613 3586642 case INT_RESULT: {
6614
1/2
✓ Branch 0 taken 3586673 times.
✗ Branch 1 not taken.
3586644 res = update_hash(&save_result.vint, sizeof(save_result.vint), INT_RESULT,
6615
1/2
✓ Branch 0 taken 3586644 times.
✗ Branch 1 not taken.
3586642 default_charset(), DERIVATION_IMPLICIT, unsigned_flag);
6616 3586673 break;
6617 }
6618 368765 case STRING_RESULT: {
6619
2/2
✓ Branch 0 taken 1570 times.
✓ Branch 1 taken 367195 times.
368765 if (!save_result.vstr) // Null value
6620
1/2
✓ Branch 0 taken 1570 times.
✗ Branch 1 not taken.
1570 res = update_hash(nullptr, 0, STRING_RESULT, &my_charset_bin,
6621 DERIVATION_IMPLICIT, false);
6622 else
6623
1/2
✓ Branch 0 taken 367199 times.
✗ Branch 1 not taken.
367194 res = update_hash(save_result.vstr->ptr(), save_result.vstr->length(),
6624 367195 STRING_RESULT, save_result.vstr->charset(),
6625 DERIVATION_IMPLICIT, false);
6626 368769 break;
6627 }
6628 3560 case DECIMAL_RESULT: {
6629
2/2
✓ Branch 0 taken 904 times.
✓ Branch 1 taken 2656 times.
3560 if (!save_result.vdec) // Null value
6630
1/2
✓ Branch 0 taken 904 times.
✗ Branch 1 not taken.
904 res = update_hash(nullptr, 0, DECIMAL_RESULT, &my_charset_bin,
6631 DERIVATION_IMPLICIT, false);
6632 else
6633
2/4
✓ Branch 0 taken 2656 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2656 times.
✗ Branch 3 not taken.
2656 res = update_hash(save_result.vdec, sizeof(my_decimal), DECIMAL_RESULT,
6634 default_charset(), DERIVATION_IMPLICIT, false);
6635 3560 break;
6636 }
6637 case ROW_RESULT:
6638 default:
6639 // This case should never be chosen
6640 assert(0);
6641 break;
6642 }
6643 4064012 return res;
6644 4064012 }
6645
6646 175 double Item_func_set_user_var::val_real() {
6647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 175 times.
175 assert(fixed == 1);
6648 175 check(false);
6649 175 update(); // Store expression
6650 175 return entry->val_real(&null_value);
6651 }
6652
6653 110375 longlong Item_func_set_user_var::val_int() {
6654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110375 times.
110375 assert(fixed == 1);
6655 110375 check(false);
6656 110375 update(); // Store expression
6657 110375 return entry->val_int(&null_value);
6658 }
6659
6660 62795 String *Item_func_set_user_var::val_str(String *str) {
6661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62795 times.
62795 assert(fixed == 1);
6662 62795 check(false);
6663 62795 update(); // Store expression
6664 62795 return entry->val_str(&null_value, str, decimals);
6665 }
6666
6667 90026 my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val) {
6668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90026 times.
90026 assert(fixed == 1);
6669 90026 check(false);
6670 90026 update(); // Store expression
6671 90026 return entry->val_decimal(&null_value, val);
6672 }
6673
6674 // just the assignment, for use in "SET @a:=5" type self-prints
6675 55 void Item_func_set_user_var::print_assignment(
6676 const THD *thd, String *str, enum_query_type query_type) const {
6677 55 str->append(STRING_WITH_LEN("@"));
6678 55 str->append(name);
6679 55 str->append(STRING_WITH_LEN(":="));
6680 55 args[0]->print(thd, str, query_type);
6681 55 }
6682
6683 // parenthesize assignment for use in "EXPLAIN EXTENDED SELECT (@e:=80)+5"
6684 55 void Item_func_set_user_var::print(const THD *thd, String *str,
6685 enum_query_type query_type) const {
6686 55 str->append(STRING_WITH_LEN("("));
6687 55 print_assignment(thd, str, query_type);
6688 55 str->append(STRING_WITH_LEN(")"));
6689 55 }
6690
6691 11189 bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg) {
6692
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 11165 times.
11189 if (result_field) {
6693 24 check(true);
6694 24 update();
6695 /*
6696 TODO This func have to be changed to avoid sending data as a field.
6697 */
6698 24 return protocol->store_field(result_field);
6699 }
6700 11165 return Item::send(protocol, str_arg);
6701 }
6702
6703 3180 void Item_func_set_user_var::make_field(Send_field *tmp_field) {
6704
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3171 times.
3180 if (result_field) {
6705 9 result_field->make_send_field(tmp_field);
6706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(tmp_field->table_name != nullptr);
6707
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (Item::item_name.is_set())
6708 9 tmp_field->col_name = Item::item_name.ptr(); // Use user supplied name
6709 } else
6710 3171 Item::make_field(tmp_field);
6711 3180 }
6712
6713 /*
6714 Save the value of a user variable into a field
6715
6716 SYNOPSIS
6717 save_in_field()
6718 field target field to save the value to
6719 no_conversion flag indicating whether conversions are allowed
6720
6721 DESCRIPTION
6722 Save the function value into a field and update the user variable
6723 accordingly. If a result field is defined and the target field doesn't
6724 coincide with it then the value from the result field will be used as
6725 the new value of the user variable.
6726
6727 The reason to have this method rather than simply using the result
6728 field in the val_xxx() methods is that the value from the result field
6729 not always can be used when the result field is defined.
6730 Let's consider the following cases:
6731 1) when filling a tmp table the result field is defined but the value of it
6732 is undefined because it has to be produced yet. Thus we can't use it.
6733 2) on execution of an INSERT ... SELECT statement the save_in_field()
6734 function will be called to fill the data in the new record. If the SELECT
6735 part uses a tmp table then the result field is defined and should be
6736 used in order to get the correct result.
6737
6738 The difference between the SET_USER_VAR function and regular functions
6739 like CONCAT is that the Item_func objects for the regular functions are
6740 replaced by Item_field objects after the values of these functions have
6741 been stored in a tmp table. Yet an object of the Item_field class cannot
6742 be used to update a user variable.
6743 Due to this we have to handle the result field in a special way here and
6744 in the Item_func_set_user_var::send() function.
6745
6746 RETURN VALUES
6747 TYPE_OK Ok
6748 Everything else Error
6749 */
6750
6751 2964588 type_conversion_status Item_func_set_user_var::save_in_field(
6752 Field *field, bool no_conversions, bool can_use_result_field) {
6753 2964588 bool use_result_field =
6754
6/6
✓ Branch 0 taken 2964544 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 143677 times.
✓ Branch 3 taken 2820867 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 143672 times.
2964588 (!can_use_result_field ? 0 : (result_field && result_field != field));
6755 type_conversion_status error;
6756
6757 /* Update the value of the user variable */
6758 2964588 check(use_result_field);
6759 2964588 update();
6760
6761
4/4
✓ Branch 0 taken 2886527 times.
✓ Branch 1 taken 78061 times.
✓ Branch 2 taken 78071 times.
✓ Branch 3 taken 2886517 times.
5851115 if (result_type() == STRING_RESULT ||
6762
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 2886487 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 30 times.
2886527 (result_type() == REAL_RESULT && field->result_type() == STRING_RESULT)) {
6763 String *result;
6764 78071 const CHARSET_INFO *cs = collation.collation;
6765 char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
6766 78071 str_value.set_quick(buff, sizeof(buff), cs);
6767
1/2
✓ Branch 0 taken 78071 times.
✗ Branch 1 not taken.
78071 result = entry->val_str(&null_value, &str_value, decimals);
6768
6769
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 78069 times.
78071 if (null_value) {
6770 2 str_value.set_quick(nullptr, 0, cs);
6771
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return set_field_to_null_with_conversions(field, no_conversions);
6772 }
6773
6774 /* NOTE: If null_value == false, "result" must be not NULL. */
6775
6776
1/2
✓ Branch 0 taken 78069 times.
✗ Branch 1 not taken.
78069 field->set_notnull();
6777
1/2
✓ Branch 0 taken 78069 times.
✗ Branch 1 not taken.
78069 error = field->store(result->ptr(), result->length(), cs);
6778 78069 str_value.set_quick(nullptr, 0, cs);
6779
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 2886487 times.
2886517 } else if (result_type() == REAL_RESULT) {
6780 30 double nr = entry->val_real(&null_value);
6781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (null_value) return set_field_to_null(field);
6782 30 field->set_notnull();
6783 30 error = field->store(nr);
6784
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 2886464 times.
2886487 } else if (result_type() == DECIMAL_RESULT) {
6785 23 my_decimal decimal_value;
6786
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 my_decimal *val = entry->val_decimal(&null_value, &decimal_value);
6787
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
23 if (null_value) return set_field_to_null(field);
6788
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 field->set_notnull();
6789
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 error = field->store_decimal(val);
6790
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 2 times.
23 } else {
6791 2886464 longlong nr = entry->val_int(&null_value);
6792
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2886461 times.
2886464 if (null_value)
6793 3 return set_field_to_null_with_conversions(field, no_conversions);
6794 2886461 field->set_notnull();
6795 2886461 error = field->store(nr, unsigned_flag);
6796 }
6797 2964581 return error;
6798 }
6799
6800 1773282 String *Item_func_get_user_var::val_str(String *str) {
6801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1773282 times.
1773282 assert(fixed);
6802
1/2
✓ Branch 0 taken 1773313 times.
✗ Branch 1 not taken.
1773282 DBUG_TRACE;
6803
1/2
✓ Branch 0 taken 1773313 times.
✗ Branch 1 not taken.
1773313 THD *thd = current_thd;
6804
3/4
✓ Branch 0 taken 413939 times.
✓ Branch 1 taken 1359374 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1773314 times.
2187253 if (var_entry == nullptr &&
6805
2/4
✓ Branch 0 taken 413940 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 413940 times.
413939 get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry))
6806 return error_str();
6807
3/4
✓ Branch 0 taken 393 times.
✓ Branch 1 taken 1772921 times.
✓ Branch 2 taken 393 times.
✗ Branch 3 not taken.
1773314 if (var_entry == nullptr) return error_str(); // No such variable
6808
1/2
✓ Branch 0 taken 1772899 times.
✗ Branch 1 not taken.
1772921 String *res = var_entry->val_str(&null_value, str, decimals);
6809
7/8
✓ Branch 0 taken 1769207 times.
✓ Branch 1 taken 3692 times.
✓ Branch 2 taken 1769195 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2587 times.
✓ Branch 5 taken 1766608 times.
✓ Branch 6 taken 2587 times.
✓ Branch 7 taken 1770300 times.
1772899 if (res && !my_charset_same(res->charset(), collation.collation)) {
6810 2587 String tmpstr;
6811 uint error;
6812
1/2
✓ Branch 0 taken 2587 times.
✗ Branch 1 not taken.
2587 if (tmpstr.copy(res->ptr(), res->length(), res->charset(),
6813
3/4
✓ Branch 0 taken 2587 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2585 times.
5174 collation.collation, &error) ||
6814
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2585 times.
2587 error > 0) {
6815 char tmp[32];
6816
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 convert_to_printable(tmp, sizeof(tmp), res->ptr(), res->length(),
6817 res->charset(), 6);
6818
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_INVALID_CHARACTER_STRING, MYF(0), collation.collation->csname,
6819 tmp);
6820
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return error_str();
6821 }
6822
2/6
✓ Branch 0 taken 2585 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2585 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2585 if (str->copy(tmpstr)) return error_str();
6823 2585 return str;
6824 2587 }
6825 1770300 return res;
6826 1773280 }
6827
6828 581266 double Item_func_get_user_var::val_real() {
6829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 581266 times.
581266 assert(fixed);
6830 THD *thd;
6831
4/6
✓ Branch 0 taken 9430 times.
✓ Branch 1 taken 571836 times.
✓ Branch 2 taken 9430 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 581266 times.
590696 if (var_entry == nullptr && (thd = current_thd) &&
6832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9430 times.
9430 get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry))
6833 return 0.0;
6834
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 581223 times.
581266 if (var_entry == nullptr) return 0.0; // No such variable
6835 581223 return (var_entry->val_real(&null_value));
6836 }
6837
6838 91800 my_decimal *Item_func_get_user_var::val_decimal(my_decimal *dec) {
6839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91800 times.
91800 assert(fixed);
6840 THD *thd;
6841
4/6
✓ Branch 0 taken 1786 times.
✓ Branch 1 taken 90014 times.
✓ Branch 2 taken 1786 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 91800 times.
93586 if (var_entry == nullptr && (thd = current_thd) &&
6842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1786 times.
1786 get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry))
6843 return nullptr;
6844
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 91798 times.
91800 if (var_entry == nullptr) return nullptr;
6845 91798 return var_entry->val_decimal(&null_value, dec);
6846 }
6847
6848 8416249 longlong Item_func_get_user_var::val_int() {
6849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8416249 times.
8416249 assert(fixed);
6850 THD *thd;
6851
5/6
✓ Branch 0 taken 793635 times.
✓ Branch 1 taken 7622614 times.
✓ Branch 2 taken 793573 times.
✓ Branch 3 taken 66 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8416288 times.
9209857 if (var_entry == nullptr && (thd = current_thd) &&
6852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 793608 times.
793573 get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry))
6853 return 0LL;
6854
2/2
✓ Branch 0 taken 1537 times.
✓ Branch 1 taken 8414751 times.
8416288 if (var_entry == nullptr) return 0LL; // No such variable
6855 /*
6856 See bug#27969934 NO WARNING WHEN CAST OF USER VARIABLE
6857 TO NUMBER GOES WRONG.
6858 */
6859 8414751 return var_entry->val_int(&null_value);
6860 }
6861
6862 190311 const CHARSET_INFO *Item_func_get_user_var::charset_for_protocol() {
6863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 190311 times.
190311 assert(fixed);
6864 THD *thd;
6865 /*
6866 If the query reads the value of the variable's charset it depends on this
6867 variable, so the user var may need to be stored in the binlog: so we call
6868 get_var_with_binlog.
6869 */
6870
4/6
✓ Branch 0 taken 95418 times.
✓ Branch 1 taken 94893 times.
✓ Branch 2 taken 95418 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 190311 times.
285729 if (var_entry == nullptr && (thd = current_thd) &&
6871
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95418 times.
95418 get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry))
6872 return &my_charset_bin;
6873
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 189991 times.
190311 if (var_entry == nullptr) return &my_charset_bin; // No such variable
6874 // @todo WL#6570 Should we return collation of Item node or variable entry?
6875
2/2
✓ Branch 0 taken 52611 times.
✓ Branch 1 taken 137380 times.
189991 return result_type() == STRING_RESULT ? collation.collation : &my_charset_bin;
6876 }
6877
6878 /**
6879 Get variable by name and, if necessary, put the record of variable
6880 use into the binary log.
6881
6882 When a user variable is invoked from an update query (INSERT, UPDATE etc),
6883 stores this variable and its value in thd->user_var_events, so that it can be
6884 written to the binlog (will be written just before the query is written, see
6885 log.cc).
6886
6887 @param thd Current session.
6888 @param sql_command The command the variable participates in.
6889 @param name Variable name
6890 @param[out] out_entry variable structure or NULL. The pointer is set
6891 regardless of whether function succeeded or not.
6892
6893 @retval
6894 0 OK
6895 @retval
6896 1 Failed to put appropriate record into binary log
6897
6898 */
6899
6900 1314166 static int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
6901 const Name_string &name,
6902 user_var_entry **out_entry) {
6903 Binlog_user_var_event *user_var_event;
6904 user_var_entry *var_entry;
6905
6906 /* Protects thd->user_vars. */
6907
1/2
✓ Branch 0 taken 1314131 times.
✗ Branch 1 not taken.
1314166 mysql_mutex_lock(&thd->LOCK_thd_data);
6908
1/2
✓ Branch 0 taken 1314128 times.
✗ Branch 1 not taken.
1314131 var_entry = get_variable(thd, name, nullptr);
6909
1/2
✓ Branch 0 taken 1314235 times.
✗ Branch 1 not taken.
1314128 mysql_mutex_unlock(&thd->LOCK_thd_data);
6910
6911 1314235 *out_entry = var_entry;
6912
6913 /*
6914 In cases when this function is called for a sub-statement, we can't
6915 rely on OPTION_BIN_LOG flag in THD::variables.option_bits bitmap
6916 to determine whether binary logging is turned on, as this bit can be
6917 cleared before executing sub-statement. So instead we have to look
6918 at THD::variables::sql_log_bin member.
6919 */
6920
4/4
✓ Branch 0 taken 1257714 times.
✓ Branch 1 taken 56483 times.
✓ Branch 2 taken 1192941 times.
✓ Branch 3 taken 64773 times.
1314235 bool log_on = mysql_bin_log.is_open() && thd->variables.sql_log_bin;
6921
6922 /*
6923 Any reference to user-defined variable which is done from stored
6924 function or trigger affects their execution and the execution of the
6925 calling statement. We must log all such variables even if they are
6926 not involved in table-updating statements.
6927 */
6928
9/10
✓ Branch 0 taken 1192943 times.
✓ Branch 1 taken 121254 times.
✓ Branch 2 taken 1192946 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 942169 times.
✓ Branch 5 taken 250777 times.
✓ Branch 6 taken 900913 times.
✓ Branch 7 taken 41256 times.
✓ Branch 8 taken 1022168 times.
✓ Branch 9 taken 292032 times.
1314197 if (!(log_on && (is_update_query(sql_command) || thd->in_sub_stmt))) return 0;
6929
6930
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 291986 times.
292032 if (var_entry == nullptr) {
6931 /*
6932 If the variable does not exist, it's NULL, but we want to create it so
6933 that it gets into the binlog (if it didn't, the slave could be
6934 influenced by a variable of the same name previously set by another
6935 thread).
6936 We create it like if it had been explicitly set with SET before.
6937 The 'new' mimics what sql_yacc.yy does when 'SET @a=10;'.
6938 sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
6939 in dispatch_command()). Instead of building a one-element list to pass to
6940 sql_set_variables(), we could instead manually call check() and update();
6941 this would save memory and time; but calling sql_set_variables() makes
6942 one unique place to maintain (sql_set_variables()).
6943
6944 Manipulation with lex is necessary since free_underlaid_joins
6945 is going to release memory belonging to the main query.
6946 */
6947
6948 46 List<set_var_base> tmp_var_list;
6949
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 LEX *sav_lex = thd->lex, lex_tmp;
6950 46 thd->lex = &lex_tmp;
6951
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 lex_start(thd);
6952
2/4
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
92 tmp_var_list.push_back(new (thd->mem_root) set_var_user(
6953
3/6
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
✗ Branch 5 not taken.
138 new Item_func_set_user_var(name, new Item_null())));
6954 /* Create the variable */
6955
2/4
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
46 if (sql_set_variables(thd, &tmp_var_list, false)) {
6956 thd->lex = sav_lex;
6957 return 1;
6958 }
6959 46 thd->lex = sav_lex;
6960
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 mysql_mutex_lock(&thd->LOCK_thd_data);
6961
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 var_entry = get_variable(thd, name, nullptr);
6962
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 mysql_mutex_unlock(&thd->LOCK_thd_data);
6963
6964 46 *out_entry = var_entry;
6965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (var_entry == nullptr) return 1;
6966
5/6
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 234635 times.
✓ Branch 3 taken 57357 times.
✓ Branch 4 taken 57409 times.
✓ Branch 5 taken 234583 times.
526667 } else if (var_entry->used_query_id() == thd->query_id ||
6967
3/4
✓ Branch 0 taken 234635 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 234583 times.
234635 mysql_bin_log.is_query_in_union(thd, var_entry->used_query_id())) {
6968 /*
6969 If this variable was already stored in user_var_events by this query
6970 (because it's used in more than one place in the query), don't store
6971 it.
6972 */
6973 57409 return 0;
6974 }
6975
6976 /*
6977 First we need to store value of var_entry, when the next situation
6978 appears:
6979 > set @a:=1;
6980 > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
6981 We have to write to binlog value @a= 1.
6982
6983 We allocate the user_var_event on user_var_events_alloc pool, not on
6984 the this-statement-execution pool because in SPs user_var_event objects
6985 may need to be valid after current [SP] statement execution pool is
6986 destroyed.
6987 */
6988 234629 size_t size = ALIGN_SIZE(sizeof(Binlog_user_var_event)) + var_entry->length();
6989 234629 if (!(user_var_event =
6990
2/4
✓ Branch 0 taken 234629 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 234629 times.
234629 (Binlog_user_var_event *)thd->user_var_events_alloc->Alloc(size)))
6991 return 1;
6992
6993 234629 user_var_event->value =
6994 234629 (char *)user_var_event + ALIGN_SIZE(sizeof(Binlog_user_var_event));
6995 234629 user_var_event->user_var_event = var_entry;
6996 234629 user_var_event->type = var_entry->type();
6997 234629 user_var_event->charset_number = var_entry->collation.collation->number;
6998 234629 user_var_event->unsigned_flag = var_entry->unsigned_flag;
6999
2/2
✓ Branch 0 taken 2752 times.
✓ Branch 1 taken 231877 times.
234629 if (!var_entry->ptr()) {
7000 /* NULL value*/
7001 2752 user_var_event->length = 0;
7002 2752 user_var_event->value = nullptr;
7003 } else {
7004 // Avoid memcpy of a my_decimal object, use copy CTOR instead.
7005 231877 user_var_event->length = var_entry->length();
7006
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 231817 times.
231877 if (user_var_event->type == DECIMAL_RESULT) {
7007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 assert(var_entry->length() == sizeof(my_decimal));
7008 const my_decimal *dec = static_cast<const my_decimal *>(
7009 60 static_cast<const void *>(var_entry->ptr()));
7010 60 dec->sanity_check();
7011
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 new (user_var_event->value) my_decimal(*dec);
7012 } else
7013 231817 memcpy(user_var_event->value, var_entry->ptr(), var_entry->length());
7014 }
7015 // Mark that this variable has been used by this query
7016 234629 var_entry->set_used_query_id(thd->query_id);
7017
2/4
✓ Branch 0 taken 234629 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 234629 times.
234629 if (thd->user_var_events.push_back(user_var_event)) return 1;
7018
7019 234629 return 0;
7020 }
7021
7022 745413 bool Item_func_get_user_var::resolve_type(THD *thd) {
7023 745413 set_nullable(true);
7024
7025 /*
7026 @todo WL#6570 change has effects:
7027 - bad: in packet.test (see comment there), ps_<n><engine>.test
7028 (e.g. ps_5merge.test) (see comment in include/ps_conv.inc),
7029 ps_w_max_indexes_64
7030 - good: type_temporal_fractional.test (see comment in that file)
7031 - fixes failure of: sysschema.pr_statement_performance_analyzer and
7032 sysschema.format_statement.
7033 Don't forget to grep for "WL#6570" in the whole tree, including mtr
7034 tests.
7035 */
7036 745413 used_tables_cache =
7037
2/2
✓ Branch 0 taken 2761 times.
✓ Branch 1 taken 742652 times.
745413 thd->lex->locate_var_assignment(name) ? RAND_TABLE_BIT : INNER_TABLE_BIT;
7038
7039 745413 mysql_mutex_lock(&thd->LOCK_thd_data);
7040 745413 var_entry = get_variable(thd, name, nullptr);
7041 745414 mysql_mutex_unlock(&thd->LOCK_thd_data);
7042
7043
2/2
✓ Branch 0 taken 731668 times.
✓ Branch 1 taken 13746 times.
745414 if (var_entry != nullptr) {
7044 // Variable exists - assign type information from the entry.
7045 731668 m_cached_result_type = var_entry->type();
7046
7047
4/5
✓ Branch 0 taken 6071 times.
✓ Branch 1 taken 401455 times.
✓ Branch 2 taken 317741 times.
✓ Branch 3 taken 6400 times.
✗ Branch 4 not taken.
731667 switch (m_cached_result_type) {
7048 6071 case REAL_RESULT:
7049 6071 set_data_type_double();
7050 6071 break;
7051 401455 case INT_RESULT:
7052 401455 set_data_type_longlong();
7053 401454 unsigned_flag = var_entry->unsigned_flag;
7054 401454 break;
7055 317741 case STRING_RESULT:
7056 317741 set_data_type_string(uint32(MAX_BLOB_WIDTH - 1), var_entry->collation);
7057 317741 break;
7058 6400 case DECIMAL_RESULT:
7059 6400 set_data_type_decimal(DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE);
7060 6400 break;
7061 case ROW_RESULT: // Keep compiler happy
7062 default:
7063 assert(0);
7064 break;
7065 }
7066
7067 // Override collation for all data types
7068 731666 collation.set(var_entry->collation);
7069 } else {
7070 // Unknown user variable, assign expected type from context.
7071 13746 null_value = true;
7072 }
7073 745412 collation.set(DERIVATION_IMPLICIT);
7074
7075 // Refresh the variable entry during execution with proper binlogging.
7076 745412 var_entry = nullptr;
7077
7078 745412 return false;
7079 }
7080
7081 13742 bool Item_func_get_user_var::propagate_type(THD *,
7082 const Type_properties &type) {
7083 /*
7084 If the type is temporal: user variables don't support that type; so, we
7085 use a VARCHAR instead. Same for JSON and GEOMETRY.
7086 BIT and YEAR types are represented with LONGLONG.
7087 */
7088
10/13
✓ Branch 0 taken 13262 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 431 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 17 times.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 7 times.
✗ Branch 12 not taken.
13742 switch (type.m_type) {
7089 13262 case MYSQL_TYPE_TINY:
7090 case MYSQL_TYPE_SHORT:
7091 case MYSQL_TYPE_INT24:
7092 case MYSQL_TYPE_LONG:
7093 case MYSQL_TYPE_LONGLONG:
7094 13262 set_data_type_longlong();
7095 13262 unsigned_flag = type.m_unsigned_flag;
7096 13262 break;
7097 1 case MYSQL_TYPE_BIT:
7098 1 set_data_type_longlong();
7099 1 unsigned_flag = true;
7100 1 break;
7101 case MYSQL_TYPE_YEAR:
7102 set_data_type_longlong();
7103 break;
7104 4 case MYSQL_TYPE_NEWDECIMAL:
7105 case MYSQL_TYPE_DECIMAL:
7106 4 set_data_type_decimal(DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE);
7107 4 break;
7108 12 case MYSQL_TYPE_FLOAT:
7109 case MYSQL_TYPE_DOUBLE:
7110 12 set_data_type_double();
7111 12 break;
7112 431 case MYSQL_TYPE_VARCHAR:
7113 case MYSQL_TYPE_VAR_STRING:
7114 case MYSQL_TYPE_STRING:
7115 case MYSQL_TYPE_ENUM:
7116 case MYSQL_TYPE_SET:
7117 case MYSQL_TYPE_NULL:
7118 // Parameter type is VARCHAR of largest possible size
7119 431 set_data_type_string(65535U / type.m_collation.collation->mbmaxlen,
7120 431 type.m_collation);
7121 431 break;
7122 1 case MYSQL_TYPE_GEOMETRY:
7123 1 set_data_type_string(MAX_BLOB_WIDTH, type.m_collation);
7124 1 break;
7125 3 case MYSQL_TYPE_JSON:
7126 3 set_data_type_string(MAX_BLOB_WIDTH, type.m_collation);
7127 3 break;
7128 17 case MYSQL_TYPE_TINY_BLOB:
7129 case MYSQL_TYPE_MEDIUM_BLOB:
7130 case MYSQL_TYPE_LONG_BLOB:
7131 case MYSQL_TYPE_BLOB:
7132 // Parameter type is BLOB of largest possible size
7133 17 set_data_type_string(MAX_BLOB_WIDTH, type.m_collation);
7134 17 break;
7135 4 case MYSQL_TYPE_DATETIME:
7136 case MYSQL_TYPE_DATETIME2:
7137 case MYSQL_TYPE_TIMESTAMP:
7138 case MYSQL_TYPE_TIMESTAMP2:
7139 4 set_data_type_string(26, type.m_collation);
7140 4 break;
7141 case MYSQL_TYPE_DATE:
7142 case MYSQL_TYPE_NEWDATE:
7143 set_data_type_string(10, type.m_collation);
7144 break;
7145 7 case MYSQL_TYPE_TIME:
7146 case MYSQL_TYPE_TIME2:
7147 7 set_data_type_string(15, type.m_collation);
7148 7 break;
7149 default:
7150 assert(false);
7151 }
7152 // User variables have implicit derivation
7153 13742 collation.set(DERIVATION_IMPLICIT);
7154
7155 // @todo - when result_type is refactored, this may not be necessary
7156 13742 m_cached_result_type = type_to_result(data_type());
7157
7158 13742 return false;
7159 }
7160
7161 1352580 void Item_func_get_user_var::cleanup() {
7162 1352580 Item_func::cleanup();
7163 /*
7164 Ensure that a valid user variable object is rebound on next execution. See
7165 comment in Item_func_set_user_var::cleanup().
7166 */
7167 1352637 var_entry = nullptr;
7168 1352637 }
7169
7170 3897246 enum Item_result Item_func_get_user_var::result_type() const {
7171 3897246 return m_cached_result_type;
7172 }
7173
7174 674 void Item_func_get_user_var::print(const THD *thd, String *str,
7175 enum_query_type) const {
7176 674 str->append(STRING_WITH_LEN("(@"));
7177 674 append_identifier(thd, str, name.ptr(), name.length());
7178 674 str->append(')');
7179 674 }
7180
7181 24402 bool Item_func_get_user_var::eq(const Item *item, bool) const {
7182 /* Assume we don't have rtti */
7183
2/2
✓ Branch 0 taken 8496 times.
✓ Branch 1 taken 15906 times.
24402 if (this == item) return true; // Same item is same.
7184 /* Check if other type is also a get_user_var() object */
7185
4/4
✓ Branch 0 taken 8741 times.
✓ Branch 1 taken 7165 times.
✓ Branch 2 taken 14318 times.
✓ Branch 3 taken 1588 times.
24647 if (item->type() != FUNC_ITEM ||
7186
2/2
✓ Branch 0 taken 7153 times.
✓ Branch 1 taken 1588 times.
8741 down_cast<const Item_func *>(item)->functype() != functype())
7187 14318 return false;
7188 const Item_func_get_user_var *other =
7189 1588 down_cast<const Item_func_get_user_var *>(item);
7190 1588 return name.eq_bin(other->name);
7191 }
7192
7193 13717 bool Item_func_get_user_var::set_value(THD *thd, sp_rcontext * /*ctx*/,
7194 Item **it) {
7195
2/4
✓ Branch 0 taken 13717 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13717 times.
✗ Branch 3 not taken.
13717 Item_func_set_user_var *suv = new Item_func_set_user_var(name, *it);
7196 /*
7197 Item_func_set_user_var is not fixed after construction, call
7198 fix_fields().
7199 */
7200
3/6
✓ Branch 0 taken 13717 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13717 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13717 times.
✗ Branch 5 not taken.
27434 return (!suv || suv->fix_fields(thd, it) || suv->check(false) ||
7201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13717 times.
27434 suv->update());
7202 }
7203
7204 61 bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) {
7205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 assert(fixed == 0);
7206
7207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 assert(thd->lex->sql_command == SQLCOM_LOAD);
7208 auto exchange_cs =
7209 61 down_cast<Sql_cmd_load_table *>(thd->lex->m_sql_cmd)->m_exchange.cs;
7210 /*
7211 Let us set the same collation which is used for loading
7212 of fields in LOAD DATA INFILE.
7213 (Since Item_user_var_as_out_param is used only there).
7214 */
7215 61 const CHARSET_INFO *cs =
7216
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 2 times.
61 exchange_cs ? exchange_cs : thd->variables.collation_database;
7217
7218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if (Item::fix_fields(thd, ref)) return true;
7219
7220 /* Protects thd->user_vars. */
7221 61 mysql_mutex_lock(&thd->LOCK_thd_data);
7222 61 entry = get_variable(thd, name, cs);
7223
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 if (entry != nullptr) entry->set_type(STRING_RESULT);
7224 61 mysql_mutex_unlock(&thd->LOCK_thd_data);
7225
7226 61 return entry == nullptr;
7227 }
7228
7229 26 void Item_user_var_as_out_param::set_null_value(const CHARSET_INFO *) {
7230 26 entry->lock();
7231 26 entry->set_null_value(STRING_RESULT);
7232 26 entry->unlock();
7233 26 }
7234
7235 838 void Item_user_var_as_out_param::set_value(const char *str, size_t length,
7236 const CHARSET_INFO *cs) {
7237 838 entry->lock();
7238 838 entry->store(str, length, STRING_RESULT, cs, DERIVATION_IMPLICIT,
7239 false /* unsigned_arg */);
7240 838 entry->unlock();
7241 838 }
7242
7243 double Item_user_var_as_out_param::val_real() {
7244 assert(0);
7245 return 0.0;
7246 }
7247
7248 longlong Item_user_var_as_out_param::val_int() {
7249 assert(0);
7250 return 0;
7251 }
7252
7253 String *Item_user_var_as_out_param::val_str(String *) {
7254 assert(0);
7255 return nullptr;
7256 }
7257
7258 my_decimal *Item_user_var_as_out_param::val_decimal(my_decimal *) {
7259 assert(0);
7260 return nullptr;
7261 }
7262
7263 14 void Item_user_var_as_out_param::print(const THD *thd, String *str,
7264 enum_query_type) const {
7265 14 str->append('@');
7266 14 append_identifier(thd, str, name.ptr(), name.length());
7267 14 }
7268
7269 581941 Item_func_get_system_var::Item_func_get_system_var(
7270 581941 const System_variable_tracker &var_tracker, enum_var_type scope)
7271
1/2
✓ Branch 0 taken 581941 times.
✗ Branch 1 not taken.
581941 : var_scope{scope}, cache_present{0}, var_tracker{var_tracker} {
7272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 581941 times.
581941 assert(scope != OPT_DEFAULT);
7273 581941 }
7274
7275 506898 bool Item_func_get_system_var::resolve_type(THD *) {
7276 506898 set_nullable(true);
7277
7278
5/6
✓ Branch 0 taken 150230 times.
✓ Branch 1 taken 544 times.
✓ Branch 2 taken 246656 times.
✓ Branch 3 taken 109145 times.
✓ Branch 4 taken 324 times.
✗ Branch 5 not taken.
506899 switch (var_tracker.cached_show_type()) {
7279 150230 case SHOW_LONG:
7280 case SHOW_INT:
7281 case SHOW_HA_ROWS:
7282 case SHOW_LONGLONG:
7283 150230 set_data_type_longlong();
7284 150229 unsigned_flag = true;
7285 150229 break;
7286 544 case SHOW_SIGNED_INT:
7287 case SHOW_SIGNED_LONG:
7288 case SHOW_SIGNED_LONGLONG:
7289 544 set_data_type_longlong();
7290 544 unsigned_flag = false;
7291 544 break;
7292 246656 case SHOW_CHAR:
7293 case SHOW_CHAR_PTR:
7294 case SHOW_LEX_STRING:
7295 246656 collation.set(system_charset_info, DERIVATION_SYSCONST);
7296 246657 set_data_type_string(65535U / collation.collation->mbmaxlen);
7297 246659 break;
7298 109145 case SHOW_BOOL:
7299 case SHOW_MY_BOOL:
7300 109145 set_data_type_longlong();
7301 109145 max_length = 1;
7302 109145 break;
7303 324 case SHOW_DOUBLE:
7304 324 set_data_type_double();
7305 // Override decimals and length calculation done above.
7306 324 decimals = 6;
7307 324 max_length = float_length(decimals);
7308 324 break;
7309 default:
7310 my_error(ER_VAR_CANT_BE_READ, MYF(0), var_tracker.get_var_name());
7311 return true;
7312 }
7313 506901 return false;
7314 }
7315
7316 41 void Item_func_get_system_var::print(const THD *, String *str,
7317 enum_query_type) const {
7318 41 str->append(item_name);
7319 41 }
7320
7321 653158 Audit_global_variable_get_event::Audit_global_variable_get_event(
7322 653158 THD *thd, Item_func_get_system_var *item, uchar cache_type)
7323 653158 : m_thd(thd), m_item(item), m_val_type(cache_type) {
7324 // Variable is of GLOBAL scope.
7325 653158 bool is_global_var = m_item->var_scope == OPT_GLOBAL;
7326
7327 // Event is already audited for the same query.
7328 653158 bool event_is_audited =
7329
3/4
✓ Branch 0 taken 745 times.
✓ Branch 1 taken 652413 times.
✓ Branch 2 taken 745 times.
✗ Branch 3 not taken.
653158 m_item->cache_present != 0 && m_item->used_query_id == m_thd->query_id;
7330
7331
4/4
✓ Branch 0 taken 543993 times.
✓ Branch 1 taken 109165 times.
✓ Branch 2 taken 543303 times.
✓ Branch 3 taken 690 times.
653158 m_audit_event = (is_global_var && !event_is_audited);
7332 653158 }
7333
7334 653181 Audit_global_variable_get_event::~Audit_global_variable_get_event() {
7335 /*
7336 While converting value to string, integer or real type, if the value is
7337 cached for the types other then m_val_type for intermediate type
7338 conversions then event is already notified.
7339 */
7340 653181 bool event_already_notified = (m_item->cache_present & (~m_val_type));
7341
7342
4/4
✓ Branch 0 taken 543308 times.
✓ Branch 1 taken 109873 times.
✓ Branch 2 taken 513844 times.
✓ Branch 3 taken 29464 times.
653181 if (m_audit_event && !event_already_notified) {
7343 513844 String str;
7344 513844 String *outStr = nullptr;
7345
7346
4/6
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 513524 times.
✓ Branch 2 taken 320 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 513844 times.
✗ Branch 5 not taken.
513844 if (!m_item->cached_null_value || !m_thd->is_error()) {
7347 513844 outStr = &str;
7348
7349
2/4
✓ Branch 0 taken 513844 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 513844 times.
✗ Branch 3 not taken.
513844 assert(m_item->cache_present != 0 &&
7350 m_item->used_query_id == m_thd->query_id);
7351
7352
2/2
✓ Branch 0 taken 330277 times.
✓ Branch 1 taken 183567 times.
513844 if (m_item->cache_present & GET_SYS_VAR_CACHE_STRING)
7353 330277 outStr = &m_item->cached_strval;
7354
2/2
✓ Branch 0 taken 183416 times.
✓ Branch 1 taken 151 times.
183567 else if (m_item->cache_present & GET_SYS_VAR_CACHE_LONG)
7355 183416 str.set(m_item->cached_llval, m_item->collation.collation);
7356
1/2
✓ Branch 0 taken 151 times.
✗ Branch 1 not taken.
151 else if (m_item->cache_present & GET_SYS_VAR_CACHE_DOUBLE)
7357 151 str.set_real(m_item->cached_dval, m_item->decimals,
7358 151 m_item->collation.collation);
7359 }
7360
7361
2/4
✓ Branch 0 taken 513844 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 513844 times.
✗ Branch 3 not taken.
1541530 mysql_audit_notify(m_thd, AUDIT_EVENT(MYSQL_AUDIT_GLOBAL_VARIABLE_GET),
7362 513842 m_item->var_tracker.get_var_name(),
7363 513844 outStr ? outStr->ptr() : nullptr,
7364 513844 outStr ? outStr->length() : 0);
7365 513842 }
7366 653181 }
7367
7368 template <typename T>
7369 525058 longlong Item_func_get_system_var::get_sys_var_safe(THD *thd, sys_var *var) {
7370 525058 T value = {};
7371 {
7372 525058 MUTEX_LOCK(lock, &LOCK_global_system_variables);
7373 525058 std::string_view keycache_name = var_tracker.get_keycache_name();
7374 525058 value =
7375
1/2
✓ Branch 0 taken 262529 times.
✗ Branch 1 not taken.
525058 *pointer_cast<const T *>(var->value_ptr(thd, var_scope, keycache_name));
7376 525058 }
7377 525058 cache_present |= GET_SYS_VAR_CACHE_LONG;
7378 525058 used_query_id = thd->query_id;
7379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262529 times.
525058 cached_llval = null_value ? 0LL : static_cast<longlong>(value);
7380 525058 cached_null_value = null_value;
7381 525058 return cached_llval;
7382 }
7383
7384 263014 longlong Item_func_get_system_var::val_int() {
7385
1/2
✓ Branch 0 taken 263015 times.
✗ Branch 1 not taken.
263014 THD *thd = current_thd;
7386 Audit_global_variable_get_event audit_sys_var(thd, this,
7387
1/2
✓ Branch 0 taken 263016 times.
✗ Branch 1 not taken.
263015 GET_SYS_VAR_CACHE_LONG);
7388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 263016 times.
263016 assert(fixed);
7389
7390
3/4
✓ Branch 0 taken 487 times.
✓ Branch 1 taken 262529 times.
✓ Branch 2 taken 487 times.
✗ Branch 3 not taken.
263016 if (cache_present && thd->query_id == used_query_id) {
7391
1/2
✓ Branch 0 taken 487 times.
✗ Branch 1 not taken.
487 if (cache_present & GET_SYS_VAR_CACHE_LONG) {
7392 487 null_value = cached_null_value;
7393 487 return cached_llval;
7394 } else if (cache_present & GET_SYS_VAR_CACHE_DOUBLE) {
7395 null_value = cached_null_value;
7396 cached_llval = (longlong)cached_dval;
7397 cache_present |= GET_SYS_VAR_CACHE_LONG;
7398 return cached_llval;
7399 } else if (cache_present & GET_SYS_VAR_CACHE_STRING) {
7400 null_value = cached_null_value;
7401 if (!null_value)
7402 cached_llval = longlong_from_string_with_check(
7403 cached_strval.charset(), cached_strval.c_ptr(),
7404 cached_strval.c_ptr() + cached_strval.length(), unsigned_flag);
7405 else
7406 cached_llval = 0;
7407 cache_present |= GET_SYS_VAR_CACHE_LONG;
7408 return cached_llval;
7409 }
7410 }
7411
7412 262531 auto f = [this, thd](const System_variable_tracker &,
7413 262536 sys_var *var) -> longlong {
7414
9/12
✓ Branch 0 taken 19271 times.
✓ Branch 1 taken 124655 times.
✓ Branch 2 taken 8599 times.
✓ Branch 3 taken 140 times.
✓ Branch 4 taken 271 times.
✓ Branch 5 taken 133 times.
✓ Branch 6 taken 73 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 109387 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
262531 switch (var->show_type()) {
7415 19271 case SHOW_INT:
7416 19271 return get_sys_var_safe<uint>(thd, var);
7417 124655 case SHOW_LONG:
7418 124655 return get_sys_var_safe<ulong>(thd, var);
7419 8599 case SHOW_LONGLONG:
7420 8599 return get_sys_var_safe<ulonglong>(thd, var);
7421 140 case SHOW_SIGNED_INT:
7422 140 return get_sys_var_safe<int>(thd, var);
7423 271 case SHOW_SIGNED_LONG:
7424 271 return get_sys_var_safe<long>(thd, var);
7425 133 case SHOW_SIGNED_LONGLONG:
7426 133 return get_sys_var_safe<longlong>(thd, var);
7427 73 case SHOW_HA_ROWS:
7428 73 return get_sys_var_safe<ha_rows>(thd, var);
7429 case SHOW_BOOL:
7430 return get_sys_var_safe<bool>(thd, var);
7431 109387 case SHOW_MY_BOOL:
7432 109387 return get_sys_var_safe<bool>(thd, var);
7433 case SHOW_DOUBLE: {
7434 double dval = val_real();
7435
7436 used_query_id = thd->query_id;
7437 cached_llval = (longlong)dval;
7438 cache_present |= GET_SYS_VAR_CACHE_LONG;
7439 return cached_llval;
7440 }
7441 2 case SHOW_CHAR:
7442 case SHOW_CHAR_PTR:
7443 case SHOW_LEX_STRING: {
7444 2 String *str_val = val_str(nullptr);
7445 // Treat empty strings as NULL, like val_real() does.
7446
5/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 if (str_val && str_val->length())
7447 1 cached_llval = longlong_from_string_with_check(
7448 1 system_charset_info, str_val->c_ptr(),
7449 1 str_val->c_ptr() + str_val->length(), unsigned_flag);
7450 else {
7451 1 null_value = true;
7452 1 cached_llval = 0;
7453 }
7454
7455 2 cache_present |= GET_SYS_VAR_CACHE_LONG;
7456 2 return cached_llval;
7457 }
7458
7459 default:
7460 my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
7461 return 0; // keep the compiler happy
7462 }
7463 262529 };
7464
1/2
✓ Branch 0 taken 262531 times.
✗ Branch 1 not taken.
262529 return var_tracker.access_system_variable<longlong>(thd, f).value_or(0);
7465 263018 }
7466
7467 387097 String *Item_func_get_system_var::val_str(String *str) {
7468
4/6
✓ Branch 0 taken 386083 times.
✓ Branch 1 taken 1027 times.
✓ Branch 2 taken 386086 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 386102 times.
✗ Branch 5 not taken.
387097 DEBUG_SYNC(current_thd, "after_error_checking");
7469
1/2
✓ Branch 0 taken 387128 times.
✗ Branch 1 not taken.
387129 THD *thd = current_thd;
7470 Audit_global_variable_get_event audit_sys_var(thd, this,
7471
1/2
✓ Branch 0 taken 387128 times.
✗ Branch 1 not taken.
387128 GET_SYS_VAR_CACHE_STRING);
7472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 387128 times.
387128 assert(fixed);
7473
7474
3/4
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 386876 times.
✓ Branch 2 taken 252 times.
✗ Branch 3 not taken.
387128 if (cache_present && thd->query_id == used_query_id) {
7475
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 10 times.
252 if (cache_present & GET_SYS_VAR_CACHE_STRING) {
7476 242 null_value = cached_null_value;
7477
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 238 times.
242 return null_value ? nullptr : &cached_strval;
7478
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 } else if (cache_present & GET_SYS_VAR_CACHE_LONG) {
7479 10 null_value = cached_null_value;
7480
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 if (!null_value) cached_strval.set(cached_llval, collation.collation);
7481 10 cache_present |= GET_SYS_VAR_CACHE_STRING;
7482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 return null_value ? nullptr : &cached_strval;
7483 } else if (cache_present & GET_SYS_VAR_CACHE_DOUBLE) {
7484 null_value = cached_null_value;
7485 if (!null_value)
7486 cached_strval.set_real(cached_dval, decimals, collation.collation);
7487 cache_present |= GET_SYS_VAR_CACHE_STRING;
7488 return null_value ? nullptr : &cached_strval;
7489 }
7490 }
7491
7492 386876 str = &cached_strval;
7493 386876 null_value = false;
7494
7495 1520914 auto f = [this, thd, &str](const System_variable_tracker &, sys_var *var) {
7496
2/4
✓ Branch 0 taken 360031 times.
✓ Branch 1 taken 26839 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
386861 switch (var->show_type()) {
7497 360031 case SHOW_CHAR:
7498 case SHOW_CHAR_PTR:
7499 case SHOW_LEX_STRING: {
7500 360031 mysql_mutex_lock(&LOCK_global_system_variables);
7501 const char *cptr =
7502 360039 var->show_type() == SHOW_CHAR
7503
2/2
✓ Branch 0 taken 202701 times.
✓ Branch 1 taken 157338 times.
720078 ? pointer_cast<const char *>(var->value_ptr(
7504 202701 thd, var_scope, var_tracker.get_keycache_name()))
7505 314676 : *pointer_cast<const char *const *>(var->value_ptr(
7506 157338 thd, var_scope, var_tracker.get_keycache_name()));
7507
2/2
✓ Branch 0 taken 359650 times.
✓ Branch 1 taken 389 times.
360039 if (cptr) {
7508 size_t len =
7509 359650 var->show_type() == SHOW_LEX_STRING
7510
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 359521 times.
359779 ? (pointer_cast<const LEX_STRING *>(var->value_ptr(
7511 129 thd, var_scope, var_tracker.get_keycache_name())))
7512 ->length
7513 359521 : strlen(cptr);
7514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 359650 times.
359650 if (str->copy(cptr, len, collation.collation)) {
7515 null_value = true;
7516 str = nullptr;
7517 }
7518 } else {
7519 389 null_value = true;
7520 389 str = nullptr;
7521 }
7522 360039 mysql_mutex_unlock(&LOCK_global_system_variables);
7523 360039 break;
7524 }
7525
7526 26839 case SHOW_INT:
7527 case SHOW_LONG:
7528 case SHOW_LONGLONG:
7529 case SHOW_SIGNED_INT:
7530 case SHOW_SIGNED_LONG:
7531 case SHOW_SIGNED_LONGLONG:
7532 case SHOW_HA_ROWS:
7533 case SHOW_BOOL:
7534 case SHOW_MY_BOOL:
7535
2/2
✓ Branch 0 taken 26838 times.
✓ Branch 1 taken 1 times.
26839 if (unsigned_flag)
7536 26838 str->set((ulonglong)val_int(), collation.collation);
7537 else
7538 1 str->set(val_int(), collation.collation);
7539 26839 break;
7540 case SHOW_DOUBLE:
7541 str->set_real(val_real(), decimals, collation.collation);
7542 break;
7543
7544 default:
7545 my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
7546 str = error_str();
7547 break;
7548 }
7549 773754 };
7550
3/6
✓ Branch 0 taken 386867 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 386878 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 386878 times.
386876 if (var_tracker.access_system_variable(thd, f)) {
7551 str = error_str();
7552 }
7553
7554 386878 cache_present |= GET_SYS_VAR_CACHE_STRING;
7555 386878 used_query_id = thd->query_id;
7556 386878 cached_null_value = null_value;
7557 386878 return str;
7558 387130 }
7559
7560 3038 double Item_func_get_system_var::val_real() {
7561
1/2
✓ Branch 0 taken 3038 times.
✗ Branch 1 not taken.
3038 THD *thd = current_thd;
7562 Audit_global_variable_get_event audit_sys_var(thd, this,
7563
1/2
✓ Branch 0 taken 3038 times.
✗ Branch 1 not taken.
3038 GET_SYS_VAR_CACHE_DOUBLE);
7564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3038 times.
3038 assert(fixed);
7565
7566
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3032 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
3038 if (cache_present && thd->query_id == used_query_id) {
7567
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (cache_present & GET_SYS_VAR_CACHE_DOUBLE) {
7568 6 null_value = cached_null_value;
7569 6 return cached_dval;
7570 } else if (cache_present & GET_SYS_VAR_CACHE_LONG) {
7571 null_value = cached_null_value;
7572 cached_dval = (double)cached_llval;
7573 cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
7574 return cached_dval;
7575 } else if (cache_present & GET_SYS_VAR_CACHE_STRING) {
7576 null_value = cached_null_value;
7577 if (!null_value)
7578 cached_dval = double_from_string_with_check(
7579 cached_strval.charset(), cached_strval.c_ptr(),
7580 cached_strval.c_ptr() + cached_strval.length());
7581 else
7582 cached_dval = 0;
7583 cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
7584 return cached_dval;
7585 }
7586 }
7587
7588 3032 auto f = [this, thd](const System_variable_tracker &,
7589 7050 sys_var *var) -> double {
7590
3/4
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 2701 times.
✗ Branch 3 not taken.
3032 switch (var->show_type()) {
7591 324 case SHOW_DOUBLE:
7592 324 mysql_mutex_lock(&LOCK_global_system_variables);
7593 972 cached_dval = *pointer_cast<const double *>(
7594 324 var->value_ptr(thd, var_scope, var_tracker.get_keycache_name()));
7595 324 mysql_mutex_unlock(&LOCK_global_system_variables);
7596 324 used_query_id = thd->query_id;
7597 324 cached_null_value = null_value;
7598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 if (null_value) cached_dval = 0;
7599 324 cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
7600 324 return cached_dval;
7601 7 case SHOW_CHAR:
7602 case SHOW_LEX_STRING:
7603 case SHOW_CHAR_PTR: {
7604 7 mysql_mutex_lock(&LOCK_global_system_variables);
7605 const char *cptr =
7606 7 var->show_type() == SHOW_CHAR
7607
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
14 ? pointer_cast<const char *>(var->value_ptr(
7608 7 thd, var_scope, var_tracker.get_keycache_name()))
7609 : *pointer_cast<const char *const *>(var->value_ptr(
7610 thd, var_scope, var_tracker.get_keycache_name()));
7611 // Treat empty strings as NULL, like val_int() does.
7612
3/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1 times.
7 if (cptr && *cptr)
7613 6 cached_dval = double_from_string_with_check(system_charset_info, cptr,
7614 6 cptr + strlen(cptr));
7615 else {
7616 1 null_value = true;
7617 1 cached_dval = 0;
7618 }
7619 7 mysql_mutex_unlock(&LOCK_global_system_variables);
7620 7 used_query_id = thd->query_id;
7621 7 cached_null_value = null_value;
7622 7 cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
7623 7 return cached_dval;
7624 }
7625 2701 case SHOW_INT:
7626 case SHOW_LONG:
7627 case SHOW_LONGLONG:
7628 case SHOW_SIGNED_INT:
7629 case SHOW_SIGNED_LONG:
7630 case SHOW_SIGNED_LONGLONG:
7631 case SHOW_HA_ROWS:
7632 case SHOW_BOOL:
7633 case SHOW_MY_BOOL:
7634 2701 cached_dval = (double)val_int();
7635 2701 cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
7636 2701 used_query_id = thd->query_id;
7637 2701 cached_null_value = null_value;
7638 2701 return cached_dval;
7639 default:
7640 my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
7641 return 0;
7642 }
7643 3032 };
7644
1/2
✓ Branch 0 taken 3032 times.
✗ Branch 1 not taken.
3032 return var_tracker.access_system_variable<double>(thd, f).value_or(0);
7645 3038 }
7646
7647 bool Item_func_get_system_var::eq(const Item *item, bool) const {
7648 /* Assume we don't have rtti */
7649 if (this == item) return true; // Same item is same.
7650 /* Check if other type is also a get_user_var() object */
7651 if (item->type() != FUNC_ITEM ||
7652 down_cast<const Item_func *>(item)->functype() != functype())
7653 return false;
7654 const Item_func_get_system_var *other =
7655 down_cast<const Item_func_get_system_var *>(item);
7656 return var_tracker == other->var_tracker;
7657 }
7658
7659 624290 void Item_func_get_system_var::cleanup() {
7660 624290 Item_func::cleanup();
7661 624300 cache_present = 0;
7662 624300 cached_strval.mem_free();
7663 624302 }
7664
7665 2755 bool Item_func_match::itemize(Parse_context *pc, Item **res) {
7666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2755 times.
2755 if (skip_itemize(res)) return false;
7667
5/6
✓ Branch 0 taken 2751 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2751 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 2751 times.
2755 if (super::itemize(pc, res) || against->itemize(pc, &against)) return true;
7668 2751 add_accum_properties(against);
7669
7670 2751 pc->select->add_ftfunc_to_list(this);
7671 2751 pc->thd->lex->set_using_match();
7672
7673
2/2
✓ Branch 0 taken 2492 times.
✓ Branch 1 taken 259 times.
2751 switch (pc->select->parsing_place) {
7674 2492 case CTX_WHERE:
7675 case CTX_ON:
7676 2492 used_in_where_only = true;
7677 2492 break;
7678 259 default:
7679 259 used_in_where_only = false;
7680 }
7681
7682 2751 return false;
7683 }
7684
7685 /**
7686 Initialize searching within full-text index.
7687
7688 @param thd Thread handler
7689
7690 @returns false if success, true if error
7691 */
7692
7693 2852 bool Item_func_match::init_search(THD *thd) {
7694
1/2
✓ Branch 0 taken 2852 times.
✗ Branch 1 not taken.
2852 DBUG_TRACE;
7695
7696 /*
7697 We will skip execution if the item is not fixed
7698 with fix_field
7699 */
7700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2852 times.
2852 if (!fixed) return false;
7701
7702 2852 TABLE *const table = table_ref->table;
7703 /* Check if init_search() has been called before */
7704
3/4
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 2709 times.
✓ Branch 2 taken 143 times.
✗ Branch 3 not taken.
2852 if (ft_handler && !master) {
7705 // Update handler::ft_handler even if the search is already initialized.
7706 // If the first call to init_search() was done before we had decided if
7707 // an index scan should be used, and we later decide that we will use
7708 // one, ft_handler is not set. For example, the optimizer calls
7709 // init_search() early if it needs to call Item_func_match::get_count()
7710 // to perform COUNT(*) optimization or decide if a LIMIT clause can be
7711 // satisfied by an index scan.
7712
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 33 times.
143 if (score_from_index_scan) table->file->ft_handler = ft_handler;
7713 143 return false;
7714 }
7715
7716
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2683 times.
2709 if (key == NO_SUCH_KEY) {
7717 26 mem_root_deque<Item *> fields(thd->mem_root);
7718
3/6
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
26 fields.push_back(new Item_string(" ", 1, cmp_collation.collation));
7719
3/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 26 times.
59 for (uint i = 0; i < arg_count; i++) fields.push_back(args[i]);
7720
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 concat_ws = new Item_func_concat_ws(&fields);
7721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (concat_ws == nullptr) return true;
7722 /*
7723 Above function used only to get value and do not need fix_fields for it:
7724 Item_string - basic constant
7725 fields - fix_fields() was already called for this arguments
7726 Item_func_concat_ws - do not need fix_fields() to produce value
7727 */
7728 26 concat_ws->quick_fix_field();
7729
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 }
7730
7731
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 2615 times.
2709 if (master) {
7732
2/4
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 94 times.
94 if (master->init_search(thd)) return true;
7733
7734 94 ft_handler = master->ft_handler;
7735 94 return false;
7736 }
7737
7738 2615 String *ft_tmp = nullptr;
7739
7740 // MATCH ... AGAINST (NULL) is meaningless, but possible
7741
3/4
✓ Branch 0 taken 2615 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2612 times.
2615 if (!(ft_tmp = key_item()->val_str(&value))) {
7742 3 ft_tmp = &value;
7743
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 value.set("", 0, cmp_collation.collation);
7744 }
7745
7746
2/2
✓ Branch 0 taken 1334 times.
✓ Branch 1 taken 1281 times.
2615 if (ft_tmp->charset() != cmp_collation.collation) {
7747 uint dummy_errors;
7748
1/2
✓ Branch 0 taken 1334 times.
✗ Branch 1 not taken.
1334 search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
7749 cmp_collation.collation, &dummy_errors);
7750 1334 ft_tmp = &search_value;
7751 }
7752
7753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2615 times.
2615 if (!table->is_created()) {
7754 my_error(ER_NO_FT_MATERIALIZED_SUBQUERY, MYF(0));
7755 return true;
7756 }
7757
7758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2615 times.
2615 assert(master == nullptr);
7759
1/2
✓ Branch 0 taken 2615 times.
✗ Branch 1 not taken.
2615 ft_handler = table->file->ft_init_ext_with_hints(key, ft_tmp, get_hints());
7760
7/8
✓ Branch 0 taken 2608 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 2608 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2606 times.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 2606 times.
2615 if (ft_handler == nullptr || thd->is_error()) {
7761 9 return true;
7762 }
7763
7764
2/2
✓ Branch 0 taken 2169 times.
✓ Branch 1 taken 437 times.
2606 if (score_from_index_scan) table->file->ft_handler = ft_handler;
7765
7766 2606 return false;
7767 2852 }
7768
7769 349 float Item_func_match::get_filtering_effect(THD *, table_map filter_for_table,
7770 table_map read_tables,
7771 const MY_BITMAP *fields_to_ignore,
7772 double rows_in_table) {
7773 const Item_field *fld =
7774 349 contributes_to_filter(read_tables, filter_for_table, fields_to_ignore);
7775
2/2
✓ Branch 0 taken 217 times.
✓ Branch 1 taken 132 times.
349 if (!fld) return COND_FILTER_ALLPASS;
7776
7777 /*
7778 MATCH () ... AGAINST" is similar to "LIKE '...'" which has the
7779 same selectivity as "col BETWEEN ...".
7780 */
7781 132 return fld->get_cond_filter_default_probability(rows_in_table,
7782 132 COND_FILTER_BETWEEN);
7783 }
7784
7785 /**
7786 Add field into table read set.
7787
7788 @param field field to be added to the table read set.
7789 */
7790 3753 static void update_table_read_set(const Field *field) {
7791 3753 TABLE *table = field->table;
7792
7793
2/2
✓ Branch 0 taken 625 times.
✓ Branch 1 taken 3128 times.
3753 if (!bitmap_test_and_set(table->read_set, field->field_index()))
7794 625 table->covering_keys.intersect(field->part_of_key);
7795 3753 }
7796
7797 2735 bool Item_func_match::fix_fields(THD *thd, Item **ref) {
7798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2735 times.
2735 assert(fixed == 0);
7799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2735 times.
2735 assert(arg_count > 0);
7800 2735 Item *item = nullptr; // Safe as arg_count is > 1
7801
7802 2735 set_nullable(true);
7803
7804 /*
7805 const_item is assumed in quite a bit of places, so it would be difficult
7806 to remove; If it would ever to be removed, this should include
7807 modifications to find_best and auto_close as complement to auto_init code
7808 above.
7809 */
7810 2735 enum_mark_columns save_mark_used_columns = thd->mark_used_columns;
7811 /*
7812 Since different engines require different columns for FTS index lookup
7813 we prevent updating of table read_set in argument's ::fix_fields().
7814 */
7815 2735 thd->mark_used_columns = MARK_COLUMNS_NONE;
7816
4/6
✓ Branch 0 taken 2735 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2735 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2733 times.
5470 if (Item_func::fix_fields(thd, ref) || fix_func_arg(thd, &against) ||
7817
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2733 times.
2735 !against->const_for_execution()) {
7818 2 thd->mark_used_columns = save_mark_used_columns;
7819 2 my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST");
7820 2 return true;
7821 }
7822 2733 thd->mark_used_columns = save_mark_used_columns;
7823
7824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2733 times.
2733 if (against->propagate_type(thd)) return true;
7825
7826 2733 bool allows_multi_table_search = true;
7827
2/2
✓ Branch 0 taken 4067 times.
✓ Branch 1 taken 2726 times.
6793 for (uint i = 0; i < arg_count; i++) {
7828 4067 item = args[i] = args[i]->real_item();
7829
4/4
✓ Branch 0 taken 4065 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 4060 times.
8132 if (item->type() != Item::FIELD_ITEM ||
7830 /* Cannot use FTS index with outer table field */
7831
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4060 times.
4065 item->is_outer_reference()) {
7832 7 my_error(ER_WRONG_ARGUMENTS, MYF(0), "MATCH");
7833 7 return true;
7834 }
7835 4060 allows_multi_table_search &= allows_search_on_non_indexed_columns(
7836 4060 ((Item_field *)item)->field->table);
7837 }
7838
7839 /*
7840 Check that all columns come from the same table.
7841 We've already checked that columns in MATCH are fields so
7842 INNER_TABLE_BIT can only appear from AGAINST argument.
7843 */
7844
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2718 times.
2726 if ((used_tables_cache & ~INNER_TABLE_BIT) != item->used_tables())
7845 8 key = NO_SUCH_KEY;
7846
7847
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2718 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 3 times.
2726 if (key == NO_SUCH_KEY && !allows_multi_table_search) {
7848 5 my_error(ER_WRONG_ARGUMENTS, MYF(0), "MATCH");
7849 5 return true;
7850 }
7851 2721 table_ref = ((Item_field *)item)->table_ref;
7852
7853
1/2
✓ Branch 0 taken 2721 times.
✗ Branch 1 not taken.
2721 if (table_ref != nullptr) table_ref->set_fulltext_searched();
7854
7855 /*
7856 Here we make an assumption that if the engine supports
7857 fulltext extension(HA_CAN_FULLTEXT_EXT flag) then table
7858 can have FTS_DOC_ID column. Atm this is the only way
7859 to distinguish MyISAM and InnoDB engines.
7860 Generally table_ref should be available, but in case of
7861 a generated column's generation expression it's not. Thus
7862 we use field's table, at this moment it's already available.
7863 */
7864 2721 TABLE *const table =
7865
1/2
✓ Branch 0 taken 2721 times.
✗ Branch 1 not taken.
2721 table_ref ? table_ref->table : ((Item_field *)item)->field->table;
7866
7867
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2708 times.
2721 if (!(table->file->ha_table_flags() & HA_CAN_FULLTEXT)) {
7868 13 my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
7869 13 return true;
7870 }
7871
7872
2/2
✓ Branch 0 taken 2373 times.
✓ Branch 1 taken 335 times.
2708 if ((table->file->ha_table_flags() & HA_CAN_FULLTEXT_EXT)) {
7873 2373 Field *doc_id_field = table->fts_doc_id_field;
7874 /*
7875 Update read set with FTS_DOC_ID column so that indexes that have
7876 FTS_DOC_ID part can be considered as a covering index.
7877 */
7878
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 2036 times.
2373 if (doc_id_field)
7879 337 update_table_read_set(doc_id_field);
7880 else {
7881 /* read_set needs to be updated for MATCH arguments */
7882
2/2
✓ Branch 0 taken 2990 times.
✓ Branch 1 taken 2036 times.
5026 for (uint i = 0; i < arg_count; i++)
7883 2990 update_table_read_set(((Item_field *)args[i])->field);
7884 /*
7885 Prevent index only access by non-FTS index if table does not have
7886 FTS_DOC_ID column, find_relevance does not work properly without
7887 FTS_DOC_ID value. Decision for FTS index about index only access
7888 is made later by JOIN::fts_index_access() function.
7889 */
7890 2036 table->covering_keys.clear_all();
7891 }
7892
7893 } else {
7894 /*
7895 Since read_set is not updated for MATCH arguments
7896 it's necessary to update it here for MyISAM.
7897 */
7898
2/2
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 335 times.
761 for (uint i = 0; i < arg_count; i++)
7899 426 update_table_read_set(((Item_field *)args[i])->field);
7900 }
7901
7902
1/2
✓ Branch 0 taken 2708 times.
✗ Branch 1 not taken.
2708 if (!master) {
7903
1/2
✓ Branch 0 taken 2708 times.
✗ Branch 1 not taken.
2708 Prepared_stmt_arena_holder ps_arena_holder(thd);
7904
1/2
✓ Branch 0 taken 2708 times.
✗ Branch 1 not taken.
2708 hints = new (thd->mem_root) Ft_hints(flags);
7905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2708 times.
2708 if (!hints) {
7906 my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
7907 return true;
7908 }
7909
1/2
✓ Branch 0 taken 2708 times.
✗ Branch 1 not taken.
2708 }
7910 2708 return agg_item_collations_for_comparison(cmp_collation, func_name(), args,
7911 2708 arg_count, 0);
7912 }
7913
7914 2699 bool Item_func_match::fix_index(const THD *thd) {
7915 TABLE *table;
7916 2699 uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts = 0, keynr;
7917 2699 uint max_cnt = 0, mkeys = 0, i;
7918
7919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2699 times.
2699 if (!table_ref) goto err;
7920
7921 /*
7922 We will skip execution if the item is not fixed
7923 with fix_field
7924 */
7925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2699 times.
2699 if (!fixed) {
7926 if (allows_search_on_non_indexed_columns(table_ref->table))
7927 key = NO_SUCH_KEY;
7928
7929 return false;
7930 }
7931
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2696 times.
2699 if (key == NO_SUCH_KEY) return false;
7932
7933 2696 table = table_ref->table;
7934
2/2
✓ Branch 0 taken 10144 times.
✓ Branch 1 taken 2696 times.
12840 for (keynr = 0; keynr < table->s->keys; keynr++) {
7935
2/2
✓ Branch 0 taken 8061 times.
✓ Branch 1 taken 2083 times.
18205 if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
7936
4/4
✓ Branch 0 taken 4509 times.
✓ Branch 1 taken 3552 times.
✓ Branch 2 taken 4497 times.
✓ Branch 3 taken 12 times.
8061 (flags & FT_BOOL ? table->keys_in_use_for_query.is_set(keynr)
7937
5/6
✓ Branch 0 taken 3552 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3547 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 8044 times.
✓ Branch 5 taken 2100 times.
13696 : table->s->usable_indexes(thd).is_set(keynr)))
7938
7939 {
7940 8044 ft_to_key[fts] = keynr;
7941 8044 ft_cnt[fts] = 0;
7942 8044 fts++;
7943 }
7944 }
7945
7946
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 2651 times.
2696 if (!fts) goto err;
7947
7948
2/2
✓ Branch 0 taken 3961 times.
✓ Branch 1 taken 2651 times.
6612 for (i = 0; i < arg_count; i++) {
7949 Item_field *item =
7950
2/4
✓ Branch 0 taken 3961 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3961 times.
✗ Branch 3 not taken.
3961 down_cast<Item_field *>(unwrap_rollup_group(args[i])->real_item());
7951
2/2
✓ Branch 0 taken 10851 times.
✓ Branch 1 taken 3961 times.
14812 for (keynr = 0; keynr < fts; keynr++) {
7952 10851 KEY *ft_key = &table->key_info[ft_to_key[keynr]];
7953 10851 uint key_parts = ft_key->user_defined_key_parts;
7954
7955
2/2
✓ Branch 0 taken 14696 times.
✓ Branch 1 taken 10851 times.
25547 for (uint part = 0; part < key_parts; part++) {
7956
3/4
✓ Branch 0 taken 14696 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4726 times.
✓ Branch 3 taken 9970 times.
14696 if (item->field->eq(ft_key->key_part[part].field)) ft_cnt[keynr]++;
7957 }
7958 }
7959 }
7960
7961
2/2
✓ Branch 0 taken 8044 times.
✓ Branch 1 taken 2651 times.
10695 for (keynr = 0; keynr < fts; keynr++) {
7962
2/2
✓ Branch 0 taken 2774 times.
✓ Branch 1 taken 5270 times.
8044 if (ft_cnt[keynr] > max_cnt) {
7963 2774 mkeys = 0;
7964 2774 max_cnt = ft_cnt[mkeys] = ft_cnt[keynr];
7965 2774 ft_to_key[mkeys] = ft_to_key[keynr];
7966 2774 continue;
7967 }
7968
4/4
✓ Branch 0 taken 3073 times.
✓ Branch 1 taken 2197 times.
✓ Branch 2 taken 400 times.
✓ Branch 3 taken 2673 times.
5270 if (max_cnt && ft_cnt[keynr] == max_cnt) {
7969 400 mkeys++;
7970 400 ft_cnt[mkeys] = ft_cnt[keynr];
7971 400 ft_to_key[mkeys] = ft_to_key[keynr];
7972 400 continue;
7973 }
7974 }
7975
7976
2/2
✓ Branch 0 taken 2707 times.
✓ Branch 1 taken 12 times.
2719 for (keynr = 0; keynr <= mkeys; keynr++) {
7977 // partial keys doesn't work
7978
2/2
✓ Branch 0 taken 2697 times.
✓ Branch 1 taken 10 times.
2707 if (max_cnt < arg_count ||
7979
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 2639 times.
2697 max_cnt < table->key_info[ft_to_key[keynr]].user_defined_key_parts)
7980 68 continue;
7981
7982 2639 key = ft_to_key[keynr];
7983
7984 2639 return false;
7985 }
7986
7987 12 err:
7988
5/6
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 34 times.
114 if (table_ref != nullptr &&
7989 57 allows_search_on_non_indexed_columns(table_ref->table)) {
7990 23 key = NO_SUCH_KEY;
7991 23 return false;
7992 }
7993
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 my_error(ER_FT_MATCHING_KEY_NOT_FOUND, MYF(0));
7994 34 return true;
7995 }
7996
7997 658 bool Item_func_match::eq(const Item *item, bool binary_cmp) const {
7998 /* We ignore FT_SORTED flag when checking for equality since result is
7999 equivalent regardless of sorting */
8000
4/4
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 331 times.
✓ Branch 2 taken 358 times.
✓ Branch 3 taken 300 times.
985 if (!is_function_of_type(item, FT_FUNC) ||
8001 327 (flags | FT_SORTED) !=
8002
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 300 times.
327 (down_cast<const Item_func_match *>(item)->flags | FT_SORTED))
8003 358 return false;
8004
8005 300 const Item_func_match *ifm = down_cast<const Item_func_match *>(item);
8006
8007
6/6
✓ Branch 0 taken 293 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 270 times.
✓ Branch 3 taken 23 times.
✓ Branch 4 taken 236 times.
✓ Branch 5 taken 64 times.
570 if (key == ifm->key && table_ref == ifm->table_ref &&
8008
2/2
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 34 times.
270 key_item()->eq(ifm->key_item(), binary_cmp))
8009 236 return true;
8010
8011 64 return false;
8012 }
8013
8014 62678 double Item_func_match::val_real() {
8015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62678 times.
62678 assert(fixed);
8016
8017 // MATCH only knows how to get the score for base columns. Other types of
8018 // expressions (such as function calls or rollup columns) should have been
8019 // rejected during resolving.
8020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62678 times.
62678 assert(!has_rollup_expr());
8021
2/4
✓ Branch 0 taken 62678 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 62678 times.
129457 assert(std::all_of(args, args + arg_count, [](const Item *item) {
8022 return item->real_item()->type() == FIELD_ITEM;
8023 }));
8024
8025
1/2
✓ Branch 0 taken 62678 times.
✗ Branch 1 not taken.
62678 DBUG_TRACE;
8026
2/2
✓ Branch 0 taken 2222 times.
✓ Branch 1 taken 60456 times.
62678 if (ft_handler == nullptr) return -1.0;
8027
8028 60456 TABLE *const table = table_ref->table;
8029
6/6
✓ Branch 0 taken 60408 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 60403 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 60451 times.
60456 if (key != NO_SUCH_KEY && table->has_null_row()) // NULL row from outer join
8030 5 return 0.0;
8031
8032
3/4
✓ Branch 0 taken 60451 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50435 times.
✓ Branch 3 taken 10016 times.
60451 if (get_master()->score_from_index_scan) {
8033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50435 times.
50435 assert(table->file->ft_handler == ft_handler);
8034
1/2
✓ Branch 0 taken 50435 times.
✗ Branch 1 not taken.
50435 return ft_handler->please->get_relevance(ft_handler);
8035 }
8036
8037
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 9968 times.
10016 if (key == NO_SUCH_KEY) {
8038
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 String *a = concat_ws->val_str(&value);
8039
5/6
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 47 times.
48 if ((null_value = (a == nullptr)) || !a->length()) return 0;
8040
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 return ft_handler->please->find_relevance(ft_handler, (uchar *)a->ptr(),
8041 94 a->length());
8042 }
8043
1/2
✓ Branch 0 taken 9968 times.
✗ Branch 1 not taken.
9968 return ft_handler->please->find_relevance(ft_handler, table->record[0], 0);
8044 62678 }
8045
8046 304 void Item_func_match::print(const THD *thd, String *str,
8047 enum_query_type query_type) const {
8048 304 str->append(STRING_WITH_LEN("(match "));
8049 304 print_args(thd, str, 0, query_type);
8050 304 str->append(STRING_WITH_LEN(" against ("));
8051 304 against->print(thd, str, query_type);
8052
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 215 times.
304 if (flags & FT_BOOL)
8053 89 str->append(STRING_WITH_LEN(" in boolean mode"));
8054
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 203 times.
215 else if (flags & FT_EXPAND)
8055 12 str->append(STRING_WITH_LEN(" with query expansion"));
8056 304 str->append(STRING_WITH_LEN("))"));
8057 304 }
8058
8059 /**
8060 Function sets FT hints(LIMIT, flags) depending on
8061 various join conditions.
8062
8063 @param join Pointer to JOIN object.
8064 @param ft_flag FT flag value.
8065 @param ft_limit Limit value.
8066 @param no_cond true if MATCH is not used in WHERE condition.
8067 */
8068
8069 2390 void Item_func_match::set_hints(JOIN *join, uint ft_flag, ha_rows ft_limit,
8070 bool no_cond) {
8071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2390 times.
2390 assert(!master);
8072
8073
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 2247 times.
2390 if (!join) // used for count() optimization
8074 {
8075 143 hints->set_hint_flag(ft_flag);
8076 143 return;
8077 }
8078
8079 /* skip hints setting if there are aggregates(except of FT_NO_RANKING) */
8080
6/6
✓ Branch 0 taken 2031 times.
✓ Branch 1 taken 216 times.
✓ Branch 2 taken 2024 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 229 times.
✓ Branch 5 taken 2018 times.
4271 if (join->implicit_grouping || !join->group_list.empty() ||
8081
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2018 times.
2024 join->select_distinct) {
8082 /* 'No ranking' is possible even if aggregates are present */
8083
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 89 times.
229 if ((ft_flag & FT_NO_RANKING)) hints->set_hint_flag(FT_NO_RANKING);
8084 229 return;
8085 }
8086
8087 2018 hints->set_hint_flag(ft_flag);
8088
8089 /**
8090 Only one table is used, there is no aggregates,
8091 WHERE condition is a single MATCH expression
8092 (WHERE MATCH(..) or WHERE MATCH(..) [>=,>] value) or
8093 there is no WHERE condition.
8094 */
8095
8/8
✓ Branch 0 taken 1996 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 1986 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1944 times.
✓ Branch 5 taken 42 times.
✓ Branch 6 taken 1954 times.
✓ Branch 7 taken 64 times.
2018 if (join->primary_tables == 1 && (no_cond || is_simple_expression()))
8096 1954 hints->set_hint_limit(ft_limit);
8097 }
8098
8099 /***************************************************************************
8100 System variables
8101 ****************************************************************************/
8102
8103 /**
8104 Return value of an system variable base[.name] as a constant item.
8105
8106 @param pc Current parse context
8107 @param scope Global / session
8108 @param prefix Optional prefix part of the variable name
8109 @param suffix Trivial name of suffix part of the variable name
8110 @param unsafe_for_replication If true and if the variable is written to a
8111 binlog then mark the statement as unsafe.
8112
8113 @note
8114 If component.str = 0 then the variable name is in 'name'
8115
8116 @return
8117 - 0 : error
8118 - # : constant item
8119 */
8120
8121 582762 Item *get_system_variable(Parse_context *pc, enum_var_type scope,
8122 const LEX_CSTRING &prefix, const LEX_CSTRING &suffix,
8123 bool unsafe_for_replication) {
8124 582762 THD *thd = pc->thd;
8125
8126 enum_var_type resolved_scope;
8127 582762 bool written_to_binlog_flag = false;
8128 582634 auto f = [thd, scope, &resolved_scope, &written_to_binlog_flag](
8129 2631256 const System_variable_tracker &, sys_var *v) -> bool {
8130
2/2
✓ Branch 0 taken 280526 times.
✓ Branch 1 taken 302108 times.
582634 if (scope == OPT_DEFAULT) {
8131
2/2
✓ Branch 0 taken 72846 times.
✓ Branch 1 taken 207681 times.
280526 if (v->check_scope(OPT_SESSION)) {
8132 72846 resolved_scope = OPT_SESSION;
8133 } else {
8134 /* As there was no local variable, return the global value */
8135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207680 times.
207681 assert(v->check_scope(OPT_GLOBAL));
8136 207680 resolved_scope = OPT_GLOBAL;
8137 }
8138
2/2
✓ Branch 0 taken 301414 times.
✓ Branch 1 taken 694 times.
302108 } else if (v->check_scope(scope)) {
8139 301414 resolved_scope = scope;
8140 } else {
8141
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 666 times.
694 my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), v->name.str,
8142 scope == OPT_GLOBAL ? "SESSION" : "GLOBAL");
8143 694 return true;
8144 }
8145
8146 581940 written_to_binlog_flag = v->is_written_to_binlog(resolved_scope);
8147 581940 v->do_deprecated_warning(thd);
8148 581938 return false;
8149 582762 };
8150 System_variable_tracker var_tracker = System_variable_tracker::make_tracker(
8151
1/2
✓ Branch 0 taken 582760 times.
✗ Branch 1 not taken.
582762 to_string_view(prefix), to_string_view(suffix));
8152
4/6
✓ Branch 0 taken 582759 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 582761 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 822 times.
✓ Branch 5 taken 581940 times.
582760 if (var_tracker.access_system_variable<bool>(thd, f).value_or(true)) {
8153 822 return nullptr;
8154 }
8155
8156
4/4
✓ Branch 0 taken 575863 times.
✓ Branch 1 taken 6077 times.
✓ Branch 2 taken 564034 times.
✓ Branch 3 taken 11829 times.
581940 if (unsafe_for_replication && !written_to_binlog_flag)
8157
1/2
✓ Branch 0 taken 564035 times.
✗ Branch 1 not taken.
564034 thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE);
8158
8159 581941 thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
8160
8161
2/4
✓ Branch 0 taken 581941 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 581941 times.
✗ Branch 3 not taken.
581941 return new Item_func_get_system_var(var_tracker, resolved_scope);
8162 582763 }
8163
8164 4578 bool Item_func_row_count::itemize(Parse_context *pc, Item **res) {
8165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4578 times.
4578 if (skip_itemize(res)) return false;
8166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4578 times.
4578 if (super::itemize(pc, res)) return true;
8167
8168 4578 LEX *lex = pc->thd->lex;
8169 4578 lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
8170 4578 lex->safe_to_cache_query = false;
8171 4578 return false;
8172 }
8173
8174 400 longlong Item_func_row_count::val_int() {
8175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 400 times.
400 assert(fixed == 1);
8176 400 THD *thd = current_thd;
8177
8178 400 return thd->get_row_count_func();
8179 }
8180
8181 177368 Item_func_sp::Item_func_sp(const POS &pos, const LEX_STRING &db_name,
8182 const LEX_STRING &fn_name, bool use_explicit_name,
8183 177368 PT_item_list *opt_list)
8184 177368 : Item_func(pos, opt_list) {
8185 /*
8186 Set to false here, which is the default according to SQL standard.
8187 RETURNS NULL ON NULL INPUT can be implemented by modifying this member.
8188 */
8189 177368 null_on_null = false;
8190 177368 set_nullable(true);
8191 177368 set_stored_program();
8192
1/2
✓ Branch 0 taken 177368 times.
✗ Branch 1 not taken.
177368 THD *thd = current_thd;
8193 177368 m_name = new (thd->mem_root)
8194
1/2
✓ Branch 0 taken 177368 times.
✗ Branch 1 not taken.
177368 sp_name(to_lex_cstring(db_name), fn_name, use_explicit_name);
8195 177368 }
8196
8197 177368 bool Item_func_sp::itemize(Parse_context *pc, Item **res) {
8198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 177368 times.
177368 if (skip_itemize(res)) return false;
8199
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 177366 times.
177368 if (super::itemize(pc, res)) return true;
8200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 177366 times.
177366 if (m_name == nullptr) return true; // OOM
8201
8202 177366 THD *thd = pc->thd;
8203 177366 LEX *lex = thd->lex;
8204
8205 177366 context = lex->current_context();
8206 177366 lex->safe_to_cache_query = false;
8207
8208
2/2
✓ Branch 0 taken 71016 times.
✓ Branch 1 taken 106350 times.
177366 if (m_name->m_db.str == nullptr) {
8209
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 71014 times.
71016 if (thd->lex->copy_db_to(&m_name->m_db.str, &m_name->m_db.length)) {
8210 2 my_error(ER_NO_DB_ERROR, MYF(0));
8211 2 return true;
8212 }
8213 }
8214
8215 177364 m_name->init_qname(thd);
8216
2/4
✓ Branch 0 taken 177364 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 177364 times.
✗ Branch 3 not taken.
177364 sp_add_own_used_routine(lex, thd, Sroutine_hash_entry::FUNCTION, m_name);
8217
8218 177364 return false;
8219 }
8220
8221 236098 void Item_func_sp::cleanup() {
8222
2/2
✓ Branch 0 taken 216273 times.
✓ Branch 1 taken 19825 times.
236098 if (sp_result_field != nullptr) {
8223 216273 sp_result_field->mem_free();
8224 216273 sp_result_field->table->in_use = nullptr;
8225 }
8226 236098 m_sp = nullptr;
8227 236098 Item_func::cleanup();
8228 236098 }
8229
8230 74286 const char *Item_func_sp::func_name() const {
8231
1/2
✓ Branch 0 taken 74286 times.
✗ Branch 1 not taken.
74286 const THD *thd = current_thd;
8232 /* Calculate length to avoid reallocation of string for sure */
8233 74286 size_t len =
8234
2/2
✓ Branch 0 taken 71321 times.
✓ Branch 1 taken 2965 times.
74286 (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
8235 74286 m_name->m_name.length) *
8236 74286 2 + // characters*quoting
8237 74286 2 + // ` and `
8238
2/2
✓ Branch 0 taken 71321 times.
✓ Branch 1 taken 2965 times.
74286 (m_name->m_explicit_name ? 3 : 0) + // '`', '`' and '.' for the db
8239 1 + // end of string
8240 ALIGN_SIZE(1)); // to avoid String reallocation
8241
1/2
✓ Branch 0 taken 74286 times.
✗ Branch 1 not taken.
74286 String qname((char *)thd->mem_root->Alloc(len), len, system_charset_info);
8242
8243 74286 qname.length(0);
8244
2/2
✓ Branch 0 taken 71321 times.
✓ Branch 1 taken 2965 times.
74286 if (m_name->m_explicit_name) {
8245
1/2
✓ Branch 0 taken 71321 times.
✗ Branch 1 not taken.
71321 append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
8246
1/2
✓ Branch 0 taken 71321 times.
✗ Branch 1 not taken.
71321 qname.append('.');
8247 }
8248
1/2
✓ Branch 0 taken 74286 times.
✗ Branch 1 not taken.
74286 append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
8249 148572 return qname.ptr();
8250 74286 }
8251
8252 124214 table_map Item_func_sp::get_initial_pseudo_tables() const {
8253 /*
8254 INNER_TABLE_BIT prevents function from being evaluated in preparation phase.
8255 @todo - make this dependent on READS SQL or MODIFIES SQL.
8256 Due to bug#26422182, a function cannot be executed before tables
8257 are locked, even though it accesses no tables.
8258 */
8259
2/2
✓ Branch 0 taken 96038 times.
✓ Branch 1 taken 28176 times.
124214 return m_deterministic ? INNER_TABLE_BIT : RAND_TABLE_BIT;
8260 }
8261
8262 88 static void my_missing_function_error(const LEX_STRING &token,
8263 const char *func_name) {
8264
5/6
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 87 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 87 times.
88 if (token.length && is_lex_native_function(&token))
8265 1 my_error(ER_FUNC_INEXISTENT_NAME_COLLISION, MYF(0), func_name);
8266 else
8267 87 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", func_name);
8268 88 }
8269
8270 /**
8271 @brief Initialize the result field by creating a temporary dummy table
8272 and assign it to a newly created field object. Meta data used to
8273 create the field is fetched from the sp_head belonging to the stored
8274 procedure found in the stored procedure function cache.
8275
8276 @note This function should be called from fix_fields to init the result
8277 field. It is some what related to Item_field.
8278
8279 @see Item_field
8280
8281 @param thd A pointer to the session and thread context.
8282
8283 @return Function return error status.
8284 @retval true is returned on an error
8285 @retval false is returned on success.
8286 */
8287
8288 114273 bool Item_func_sp::init_result_field(THD *thd) {
8289 114273 LEX_CSTRING empty_name = {STRING_WITH_LEN("")};
8290
1/2
✓ Branch 0 taken 114273 times.
✗ Branch 1 not taken.
114273 DBUG_TRACE;
8291
8292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114273 times.
114273 assert(m_sp == nullptr);
8293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114273 times.
114273 assert(sp_result_field == nullptr);
8294
8295 Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler(
8296
1/2
✓ Branch 0 taken 114273 times.
✗ Branch 1 not taken.
114273 thd, context->view_error_handler, context->view_error_handler_arg);
8297
1/2
✓ Branch 0 taken 114273 times.
✗ Branch 1 not taken.
114273 m_sp = sp_find_routine(thd, enum_sp_type::FUNCTION, m_name,
8298 &thd->sp_func_cache, true);
8299
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 114185 times.
114273 if (m_sp == nullptr) {
8300
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 my_missing_function_error(m_name->m_name, m_name->m_qname.str);
8301 88 return true;
8302 }
8303
8304 114185 m_deterministic = m_sp->m_chistics->detistic;
8305
8306 /*
8307 A Field need to be attached to a Table.
8308 Below we "create" a dummy table by initializing
8309 the needed pointers.
8310 */
8311
2/4
✓ Branch 0 taken 114185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 114185 times.
✗ Branch 3 not taken.
114185 TABLE *dummy_table = new (thd->mem_root) TABLE;
8312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114185 times.
114185 if (dummy_table == nullptr) return true;
8313
2/4
✓ Branch 0 taken 114185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 114185 times.
✗ Branch 3 not taken.
114185 TABLE_SHARE *share = new (thd->mem_root) TABLE_SHARE;
8314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114185 times.
114185 if (share == nullptr) return true;
8315
8316 114185 dummy_table->s = share;
8317 114185 dummy_table->alias = "";
8318
1/2
✓ Branch 0 taken 114185 times.
✗ Branch 1 not taken.
114185 if (is_nullable()) dummy_table->set_nullable();
8319 114185 dummy_table->in_use = thd;
8320 114185 dummy_table->copy_blobs = true;
8321 114185 share->table_cache_key = empty_name;
8322 114185 share->db = empty_name;
8323 114185 share->table_name = empty_name;
8324
8325 114185 sp_result_field =
8326
1/2
✓ Branch 0 taken 114185 times.
✗ Branch 1 not taken.
114185 m_sp->create_result_field(thd, max_length, item_name.ptr(), dummy_table);
8327 114185 return sp_result_field == nullptr;
8328 114273 }
8329
8330 /**
8331 @brief Initialize local members with values from the Field interface.
8332
8333 @note called from Item::fix_fields.
8334 */
8335
8336 114180 bool Item_func_sp::resolve_type(THD *) {
8337
1/2
✓ Branch 0 taken 114180 times.
✗ Branch 1 not taken.
114180 DBUG_TRACE;
8338
8339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114180 times.
114180 assert(sp_result_field);
8340
1/2
✓ Branch 0 taken 114180 times.
✗ Branch 1 not taken.
114180 set_data_type(sp_result_field->type());
8341
1/2
✓ Branch 0 taken 114180 times.
✗ Branch 1 not taken.
114180 decimals = sp_result_field->decimals();
8342 114180 max_length = sp_result_field->field_length;
8343
1/2
✓ Branch 0 taken 114180 times.
✗ Branch 1 not taken.
114180 collation.set(sp_result_field->charset());
8344 114180 set_nullable(true);
8345 114180 unsigned_flag = sp_result_field->is_flag_set(UNSIGNED_FLAG);
8346
8347 114180 return false;
8348 114180 }
8349
8350 236948 longlong Item_func_sp::val_int() {
8351
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 236710 times.
236948 if (execute()) return error_int();
8352
2/2
✓ Branch 0 taken 24761 times.
✓ Branch 1 taken 211949 times.
236710 if (null_value) return 0;
8353 211949 return sp_result_field->val_int();
8354 }
8355
8356 156 double Item_func_sp::val_real() {
8357
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 152 times.
156 if (execute()) return error_real();
8358
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 151 times.
152 if (null_value) return 0.0;
8359 151 return sp_result_field->val_real();
8360 }
8361
8362 13 bool Item_func_sp::get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) {
8363
5/6
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 12 times.
13 if (execute() || null_value) return true;
8364 12 return sp_result_field->get_date(ltime, fuzzydate);
8365 }
8366
8367 7 bool Item_func_sp::get_time(MYSQL_TIME *ltime) {
8368
3/6
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
7 if (execute() || null_value) return true;
8369 7 return sp_result_field->get_time(ltime);
8370 }
8371
8372 1232 my_decimal *Item_func_sp::val_decimal(my_decimal *dec_buf) {
8373
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1231 times.
1232 if (execute()) return error_decimal(dec_buf);
8374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1231 times.
1231 if (null_value) return nullptr;
8375 1231 return sp_result_field->val_decimal(dec_buf);
8376 }
8377
8378 165965 String *Item_func_sp::val_str(String *str) {
8379 165965 StringBuffer<STRING_BUFFER_USUAL_SIZE> buf(str->charset());
8380
4/6
✓ Branch 0 taken 165965 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 165947 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
165965 if (execute()) return error_str();
8381
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 165823 times.
165947 if (null_value) return nullptr;
8382 /*
8383 result_field will set buf pointing to internal buffer
8384 of the resul_field. Due to this it will change any time
8385 when SP is executed. In order to prevent occasional
8386 corruption of returned value, we make here a copy.
8387 */
8388
1/2
✓ Branch 0 taken 165823 times.
✗ Branch 1 not taken.
165823 sp_result_field->val_str(&buf);
8389
1/2
✓ Branch 0 taken 165823 times.
✗ Branch 1 not taken.
165823 str->copy(buf);
8390 165823 return str;
8391 165965 }
8392
8393 6 bool Item_func_sp::val_json(Json_wrapper *result) {
8394
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (sp_result_field->type() == MYSQL_TYPE_JSON) {
8395
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (execute()) return true;
8396
8397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (null_value) return false;
8398
8399 5 Field_json *json_value = down_cast<Field_json *>(sp_result_field);
8400 5 return json_value->val_json(result);
8401 }
8402
8403 /* purecov: begin deadcode */
8404 assert(false);
8405 my_error(ER_INVALID_CAST_TO_JSON, MYF(0));
8406 return error_json();
8407 /* purecov: end */
8408 }
8409
8410 /**
8411 @brief Execute function & store value in field.
8412 Will set null_value properly only for a successful execution.
8413 @return Function returns error status.
8414 @retval false on success.
8415 @retval true if an error occurred.
8416 */
8417
8418 404327 bool Item_func_sp::execute() {
8419
1/2
✓ Branch 0 taken 404327 times.
✗ Branch 1 not taken.
404327 THD *thd = current_thd;
8420
8421 Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler(
8422
1/2
✓ Branch 0 taken 404327 times.
✗ Branch 1 not taken.
404327 thd, context->view_error_handler, context->view_error_handler_arg);
8423
8424 // Bind to an instance of the stored function:
8425
2/2
✓ Branch 0 taken 49019 times.
✓ Branch 1 taken 355308 times.
404327 if (m_sp == nullptr) {
8426
1/2
✓ Branch 0 taken 49019 times.
✗ Branch 1 not taken.
49019 m_sp = sp_setup_routine(thd, enum_sp_type::FUNCTION, m_name,
8427 &thd->sp_func_cache);
8428
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 49001 times.
49019 if (m_sp == nullptr) return true;
8429
1/2
✓ Branch 0 taken 49001 times.
✗ Branch 1 not taken.
49001 if (sp_result_field != nullptr) {
8430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49001 times.
49001 assert(sp_result_field->table->in_use == nullptr);
8431 49001 sp_result_field->table->in_use = thd;
8432 }
8433 }
8434
8435 /* Execute function and store the return value in the field. */
8436
8437
3/4
✓ Branch 0 taken 404309 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 244 times.
✓ Branch 3 taken 404065 times.
404309 if (execute_impl(thd)) {
8438 244 null_value = true;
8439
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 235 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
244 if (thd->killed) thd->send_kill_message();
8440 244 return true;
8441 }
8442
8443 /* Check that the field (the value) is not NULL. */
8444
1/2
✓ Branch 0 taken 404065 times.
✗ Branch 1 not taken.
404065 null_value = sp_result_field->is_null();
8445
8446 404065 return false;
8447 404327 }
8448
8449 /**
8450 @brief Execute function and store the return value in the field.
8451 Will set null_value properly only for a successful execution.
8452
8453 @note This function was intended to be the concrete implementation of
8454 the interface function execute. This was never realized.
8455
8456 @return The error state.
8457 @retval false on success
8458 @retval true if an error occurred.
8459 */
8460 404309 bool Item_func_sp::execute_impl(THD *thd) {
8461 404309 bool err_status = true;
8462 404309 Sub_statement_state statement_state;
8463 404309 Security_context *save_security_ctx = thd->security_context();
8464 404309 enum enum_sp_data_access access =
8465 404309 (m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS)
8466
1/2
✓ Branch 0 taken 404309 times.
✗ Branch 1 not taken.
404309 ? SP_DEFAULT_ACCESS_MAPPING
8467 404309 : m_sp->m_chistics->daccess;
8468
8469
1/2
✓ Branch 0 taken 404309 times.
✗ Branch 1 not taken.
404309 DBUG_TRACE;
8470
8471
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 404153 times.
404309 if (context->security_ctx) {
8472 /* Set view definer security context */
8473 156 thd->set_security_context(context->security_ctx);
8474 }
8475
3/4
✓ Branch 0 taken 404309 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 404308 times.
404309 if (sp_check_access(thd)) goto error;
8476
8477 /*
8478 Throw an error if a non-deterministic function is called while
8479 statement-based replication (SBR) is active.
8480 */
8481
8482
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 187604 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
187612 if (!m_deterministic && !trust_function_creators &&
8483
6/8
✓ Branch 0 taken 187612 times.
✓ Branch 1 taken 216696 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 404307 times.
591922 (access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) &&
8484 2 (mysql_bin_log.is_open() &&
8485
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 thd->variables.binlog_format == BINLOG_FORMAT_STMT)) {
8486
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_BINLOG_UNSAFE_ROUTINE, MYF(0));
8487 1 goto error;
8488 }
8489
8490 /*
8491 Disable the binlogging if this is not a SELECT statement. If this is a
8492 SELECT, leave binlogging on, so execute_function() code writes the
8493 function call into binlog.
8494 */
8495
1/2
✓ Branch 0 taken 404307 times.
✗ Branch 1 not taken.
404307 thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
8496
1/2
✓ Branch 0 taken 404307 times.
✗ Branch 1 not taken.
404307 err_status = m_sp->execute_function(thd, args, arg_count, sp_result_field);
8497
1/2
✓ Branch 0 taken 404307 times.
✗ Branch 1 not taken.
404307 thd->restore_sub_statement_state(&statement_state);
8498
8499 404309 error:
8500 404309 thd->set_security_context(save_security_ctx);
8501
8502 404309 return err_status;
8503 404309 }
8504
8505 6036 void Item_func_sp::make_field(Send_field *tmp_field) {
8506
1/2
✓ Branch 0 taken 6036 times.
✗ Branch 1 not taken.
6036 DBUG_TRACE;
8507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6036 times.
6036 assert(sp_result_field);
8508
1/2
✓ Branch 0 taken 6036 times.
✗ Branch 1 not taken.
6036 sp_result_field->make_send_field(tmp_field);
8509
1/2
✓ Branch 0 taken 6036 times.
✗ Branch 1 not taken.
6036 if (item_name.is_set()) tmp_field->col_name = item_name.ptr();
8510 6036 }
8511
8512 334544 Item_result Item_func_sp::result_type() const {
8513
1/2
✓ Branch 0 taken 334544 times.
✗ Branch 1 not taken.
334544 DBUG_TRACE;
8514
3/8
✓ Branch 0 taken 334544 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 334544 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 334544 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
334544 DBUG_PRINT("info", ("m_sp = %p", (void *)m_sp));
8515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 334544 times.
334544 assert(sp_result_field);
8516
1/2
✓ Branch 0 taken 334544 times.
✗ Branch 1 not taken.
669088 return sp_result_field->result_type();
8517 334544 }
8518
8519 205 bool Item_func_found_rows::itemize(Parse_context *pc, Item **res) {
8520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 205 times.
205 if (skip_itemize(res)) return false;
8521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 205 times.
205 if (super::itemize(pc, res)) return true;
8522 205 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
8523 205 pc->thd->lex->safe_to_cache_query = false;
8524 205 push_warning(current_thd, Sql_condition::SL_WARNING,
8525 ER_WARN_DEPRECATED_SYNTAX,
8526 205 ER_THD(current_thd, ER_WARN_DEPRECATED_FOUND_ROWS));
8527 205 return false;
8528 }
8529
8530 178 longlong Item_func_found_rows::val_int() {
8531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
178 assert(fixed == 1);
8532 178 return current_thd->found_rows();
8533 }
8534
8535 120 Field *Item_func_sp::tmp_table_field(TABLE *) {
8536
1/2
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
120 DBUG_TRACE;
8537
8538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
120 assert(sp_result_field);
8539 120 return sp_result_field;
8540 120 }
8541
8542 /**
8543 @brief Checks if requested access to function can be granted to user.
8544 If function isn't found yet, it searches function first.
8545 If function can't be found or user don't have requested access
8546 error is raised.
8547
8548 @param thd thread handler
8549
8550 @return Indication if the access was granted or not.
8551 @retval false Access is granted.
8552 @retval true Requested access can't be granted or function doesn't exists.
8553
8554 */
8555
8556 495527 bool Item_func_sp::sp_check_access(THD *thd) {
8557
1/2
✓ Branch 0 taken 495527 times.
✗ Branch 1 not taken.
495527 DBUG_TRACE;
8558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 495527 times.
495527 assert(m_sp);
8559
3/4
✓ Branch 0 taken 495527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 495524 times.
495527 if (check_routine_access(thd, EXECUTE_ACL, m_sp->m_db.str, m_sp->m_name.str,
8560 false, false))
8561 3 return true;
8562
8563 495524 return false;
8564 495527 }
8565
8566 114308 bool Item_func_sp::fix_fields(THD *thd, Item **ref) {
8567 114308 Security_context *save_security_ctx = thd->security_context();
8568
8569
1/2
✓ Branch 0 taken 114308 times.
✗ Branch 1 not taken.
114308 DBUG_TRACE;
8570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114308 times.
114308 assert(fixed == 0);
8571
8572 /*
8573 Checking privileges to execute the function while creating view and
8574 executing the function of select.
8575 */
8576
4/4
✓ Branch 0 taken 91230 times.
✓ Branch 1 taken 23078 times.
✓ Branch 2 taken 36500 times.
✓ Branch 3 taken 77808 times.
205538 if (!thd->lex->is_view_context_analysis() ||
8577
2/2
✓ Branch 0 taken 13422 times.
✓ Branch 1 taken 77808 times.
91230 (thd->lex->sql_command == SQLCOM_CREATE_VIEW)) {
8578
2/2
✓ Branch 0 taken 199 times.
✓ Branch 1 taken 36301 times.
36500 if (context->security_ctx) {
8579 /* Set view definer security context */
8580 199 thd->set_security_context(context->security_ctx);
8581 }
8582
8583 /*
8584 Check whether user has execute privilege or not
8585 */
8586
8587 Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler(
8588
1/2
✓ Branch 0 taken 36500 times.
✗ Branch 1 not taken.
36500 thd, context->view_error_handler, context->view_error_handler_arg);
8589
8590 73000 bool res = check_routine_access(thd, EXECUTE_ACL, m_name->m_db.str,
8591
1/2
✓ Branch 0 taken 36500 times.
✗ Branch 1 not taken.
36500 m_name->m_name.str, false, false);
8592 36500 thd->set_security_context(save_security_ctx);
8593
8594
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 36465 times.
36500 if (res) return res;
8595
2/2
✓ Branch 0 taken 36465 times.
✓ Branch 1 taken 35 times.
36500 }
8596
8597 /*
8598 We must call init_result_field before Item_func::fix_fields()
8599 to make m_sp and result_field members available to resolve_type(),
8600 which is called from Item_func::fix_fields().
8601 */
8602
3/4
✓ Branch 0 taken 114273 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
✓ Branch 3 taken 114185 times.
114273 if (init_result_field(thd)) return true;
8603
8604 114185 sp_pcontext *sp_ctx = m_sp->get_root_parsing_context();
8605
8606
3/4
✓ Branch 0 taken 114185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 114180 times.
114185 if (arg_count != sp_ctx->context_var_count()) {
8607
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), "FUNCTION", m_sp->m_qname.str,
8608 sp_ctx->context_var_count(), arg_count);
8609 5 return true;
8610 }
8611
8612
2/4
✓ Branch 0 taken 114180 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 114180 times.
114180 if (Item_func::fix_fields(thd, ref)) return true;
8613
8614
2/2
✓ Branch 0 taken 121175 times.
✓ Branch 1 taken 114180 times.
235355 for (uint i = 0; i < arg_count; i++) {
8615
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 121170 times.
121175 if (args[0]->data_type() == MYSQL_TYPE_INVALID) {
8616
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 sp_variable *var = sp_ctx->find_variable(i);
8617
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (args[0]->propagate_type(
8618 thd,
8619 5 is_numeric_type(var->type)
8620
4/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
12 ? Type_properties(var->type, var->field_def.is_unsigned)
8621 2 : is_string_type(var->type)
8622 ? Type_properties(var->type, var->field_def.charset)
8623 : Type_properties(var->type)))
8624 return true;
8625 }
8626 }
8627
8628
2/2
✓ Branch 0 taken 91218 times.
✓ Branch 1 taken 22962 times.
114180 if (thd->lex->is_view_context_analysis()) {
8629 /*
8630 Here we check privileges of the stored routine only during view
8631 creation, in order to validate the view. A runtime check is
8632 performed in Item_func_sp::execute(), and this method is not
8633 called during context analysis. Notice, that during view
8634 creation we do not infer into stored routine bodies and do not
8635 check privileges of its statements, which would probably be a
8636 good idea especially if the view has SQL SECURITY DEFINER and
8637 the used stored procedure has SQL SECURITY DEFINER.
8638 */
8639
3/4
✓ Branch 0 taken 91218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 91216 times.
91218 if (sp_check_access(thd)) return true;
8640 /*
8641 Try to set and restore the security context to see whether it's valid
8642 */
8643 Security_context *save_security_context;
8644
2/4
✓ Branch 0 taken 91216 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 91216 times.
91216 if (m_sp->set_security_ctx(thd, &save_security_context)) return true;
8645
1/2
✓ Branch 0 taken 91216 times.
✗ Branch 1 not taken.
91216 m_sp->m_security_ctx.restore_security_context(thd, save_security_context);
8646 }
8647
8648 // Cleanup immediately, thus execute() will always attach to the routine.
8649
1/2
✓ Branch 0 taken 114178 times.
✗ Branch 1 not taken.
114178 cleanup();
8650
8651 114178 return false;
8652 114308 }
8653
8654 9931 void Item_func_sp::update_used_tables() {
8655 9931 Item_func::update_used_tables();
8656
8657 /* This is reset by Item_func::update_used_tables(). */
8658 9931 set_stored_program();
8659 9931 }
8660
8661 103 void Item_func_sp::fix_after_pullout(Query_block *parent_query_block,
8662 Query_block *removed_query_block) {
8663 103 Item_func::fix_after_pullout(parent_query_block, removed_query_block);
8664 103 }
8665
8666 /*
8667 uuid_short handling.
8668
8669 The short uuid is defined as a longlong that contains the following bytes:
8670
8671 Bytes Comment
8672 1 Server_id & 255
8673 4 Startup time of server in seconds
8674 3 Incrementor
8675
8676 This means that an uuid is guaranteed to be unique
8677 even in a replication environment if the following holds:
8678
8679 - The last byte of the server id is unique
8680 - If you between two shutdown of the server don't get more than
8681 an average of 2^24 = 16M calls to uuid_short() per second.
8682 */
8683
8684 ulonglong uuid_value;
8685
8686 9786 void uuid_short_init() {
8687 9786 uuid_value =
8688 9786 ((((ulonglong)server_id) << 56) + (((ulonglong)server_start_time) << 24));
8689 9786 }
8690
8691 79 bool Item_func_uuid_short::itemize(Parse_context *pc, Item **res) {
8692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (skip_itemize(res)) return false;
8693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (super::itemize(pc, res)) return true;
8694 79 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
8695 79 pc->thd->lex->safe_to_cache_query = false;
8696 79 return false;
8697 }
8698
8699 75 longlong Item_func_uuid_short::val_int() {
8700 ulonglong val;
8701 75 mysql_mutex_lock(&LOCK_uuid_generator);
8702 75 val = uuid_value++;
8703 75 mysql_mutex_unlock(&LOCK_uuid_generator);
8704 75 return (longlong)val;
8705 }
8706
8707 6276 bool Item_func_version::itemize(Parse_context *pc, Item **res) {
8708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6276 times.
6276 if (skip_itemize(res)) return false;
8709
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6276 times.
6276 if (super::itemize(pc, res)) return true;
8710 6276 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
8711 6276 return false;
8712 }
8713
8714 /**
8715 Check if schema and table are hidden by NDB engine.
8716
8717 @param thd Thread handle.
8718 @param schema_name Schema name.
8719 @param table_name Table name.
8720
8721 @retval true If schema and table are hidden by NDB.
8722 @retval false If schema and table are not hidden by NDB.
8723 */
8724
8725 22202836 static inline bool is_hidden_by_ndb(THD *thd, String *schema_name,
8726 String *table_name) {
8727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22202836 times.
22202836 if (!strncmp(schema_name->ptr(), "ndb", 3)) {
8728 List<LEX_STRING> list;
8729
8730 // Check if schema is of ndb and if it is hidden by it.
8731 LEX_STRING sch_name = schema_name->lex_string();
8732 list.push_back(&sch_name);
8733 ha_find_files(thd, nullptr, nullptr, nullptr, true, &list);
8734 if (list.elements == 0) {
8735 // Schema is hidden by ndb engine.
8736 return true;
8737 }
8738
8739 // Check if table is hidden by ndb.
8740 if (table_name != nullptr) {
8741 list.clear();
8742 LEX_STRING tbl_name = table_name->lex_string();
8743 list.push_back(&tbl_name);
8744 ha_find_files(thd, schema_name->ptr(), nullptr, nullptr, false, &list);
8745 if (list.elements == 0) {
8746 // Table is hidden by ndb engine.
8747 return true;
8748 }
8749 }
8750 }
8751
8752 22202836 return false;
8753 }
8754
8755 /**
8756 @brief
8757 INFORMATION_SCHEMA picks metadata from DD using system views.
8758 In order for INFORMATION_SCHEMA to skip listing database for which
8759 the user does not have rights, the following internal functions are used.
8760
8761 Syntax:
8762 int CAN_ACCCESS_DATABASE(schema_name);
8763
8764 @returns,
8765 1 - If current user has access.
8766 0 - If not.
8767 */
8768
8769 153841 longlong Item_func_can_access_database::val_int() {
8770
1/2
✓ Branch 0 taken 153841 times.
✗ Branch 1 not taken.
153841 DBUG_TRACE;
8771
8772 // Read schema_name
8773 153841 String schema_name;
8774
1/2
✓ Branch 0 taken 153841 times.
✗ Branch 1 not taken.
153841 String *schema_name_ptr = args[0]->val_str(&schema_name);
8775
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 153840 times.
153841 if (schema_name_ptr == nullptr) {
8776 1 null_value = true;
8777 1 return 0;
8778 }
8779
8780 // Make sure we have safe string to access.
8781
1/2
✓ Branch 0 taken 153840 times.
✗ Branch 1 not taken.
153840 schema_name_ptr->c_ptr_safe();
8782
8783 // Check if schema is hidden.
8784
1/2
✓ Branch 0 taken 153840 times.
✗ Branch 1 not taken.
153840 THD *thd = current_thd;
8785
2/4
✓ Branch 0 taken 153840 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 153840 times.
153840 if (is_hidden_by_ndb(thd, schema_name_ptr, nullptr)) return 0;
8786
8787 // Skip INFORMATION_SCHEMA database
8788
3/4
✓ Branch 0 taken 153840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25450 times.
✓ Branch 3 taken 128390 times.
153840 if (is_infoschema_db(schema_name_ptr->ptr())) return 1;
8789
8790 // Skip PERFORMANCE_SCHEMA database
8791
3/4
✓ Branch 0 taken 128390 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25439 times.
✓ Branch 3 taken 102951 times.
128390 if (is_perfschema_db(schema_name_ptr->ptr())) return 1;
8792
8793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102951 times.
102951 if (lower_case_table_names == 2) {
8794 /*
8795 ACL code assumes that in l-c-t-n > 0 modes schema name passed to it
8796 is in lower case.
8797 */
8798 my_casedn_str(files_charset_info, schema_name_ptr->ptr());
8799 }
8800
8801 // Check access
8802 102951 Security_context *sctx = thd->security_context();
8803
8/16
✓ Branch 0 taken 102951 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 102951 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 147 times.
✓ Branch 5 taken 102804 times.
✓ Branch 6 taken 102951 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 102951 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 33 times.
✓ Branch 11 taken 102918 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
103098 if (!(sctx->master_access(schema_name_ptr->ptr()) &
8804 147 (DB_OP_ACLS | SHOW_DB_ACL) ||
8805
6/10
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 147 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 147 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 33 times.
✓ Branch 9 taken 114 times.
147 acl_get(thd, sctx->host().str, sctx->ip().str, sctx->priv_user().str,
8806 147 schema_name_ptr->ptr(), false) ||
8807
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 !check_grant_db(thd, schema_name_ptr->ptr()))) {
8808 33 return 0;
8809 }
8810
8811 102918 return 1;
8812 153841 }
8813
8814 2073794 static bool check_table_and_trigger_access(Item **args, bool check_trigger_acl,
8815 bool *null_value) {
8816
1/2
✓ Branch 0 taken 2073794 times.
✗ Branch 1 not taken.
2073794 DBUG_TRACE;
8817
8818 // Read schema_name, table_name
8819 2073794 String schema_name;
8820
1/2
✓ Branch 0 taken 2073794 times.
✗ Branch 1 not taken.
2073794 String *schema_name_ptr = args[0]->val_str(&schema_name);
8821 2073794 String table_name;
8822
1/2
✓ Branch 0 taken 2073794 times.
✗ Branch 1 not taken.
2073794 String *table_name_ptr = args[1]->val_str(&table_name);
8823
3/4
✓ Branch 0 taken 2073792 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2073792 times.
2073794 if (schema_name_ptr == nullptr || table_name_ptr == nullptr) {
8824 2 *null_value = true;
8825 2 return false;
8826 }
8827
8828
1/2
✓ Branch 0 taken 2073792 times.
✗ Branch 1 not taken.
2073792 const char *sch_name = schema_name_ptr->c_ptr_safe();
8829
1/2
✓ Branch 0 taken 2073792 times.
✗ Branch 1 not taken.
2073792 const char *tbl_name = table_name_ptr->c_ptr_safe();
8830
8831 // Check if table is hidden.
8832
1/2
✓ Branch 0 taken 2073792 times.
✗ Branch 1 not taken.
2073792 THD *thd = current_thd;
8833
2/4
✓ Branch 0 taken 2073792 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2073792 times.
2073792 if (is_hidden_by_ndb(thd, schema_name_ptr, table_name_ptr)) return false;
8834
8835 // Don't show compression dictionary tables in "SHOW TABLES"
8836
2/4
✓ Branch 0 taken 2073792 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2073792 times.
✗ Branch 3 not taken.
2073792 if (compression_dict::is_hardcoded(dd::String_type(sch_name),
8837
3/4
✓ Branch 0 taken 2073792 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50640 times.
✓ Branch 3 taken 2023152 times.
4147584 dd::String_type(tbl_name))) {
8838 50640 return false;
8839 }
8840
8841 // Skip INFORMATION_SCHEMA database
8842
3/4
✓ Branch 0 taken 2023152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30417 times.
✓ Branch 3 taken 1992735 times.
2023152 if (is_infoschema_db(schema_name_ptr->ptr())) return true;
8843
8844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1992735 times.
1992735 if (lower_case_table_names == 2) {
8845 /*
8846 ACL code assumes that in l-c-t-n > 0 modes schema and table names
8847 passed to it are in lower case.
8848 */
8849 schema_name_ptr->length(
8850 my_casedn_str(files_charset_info, schema_name_ptr->ptr()));
8851 table_name_ptr->length(
8852 my_casedn_str(files_charset_info, table_name_ptr->ptr()));
8853 }
8854
8855 // Check access
8856 1992735 ulong db_access = 0;
8857
2/4
✓ Branch 0 taken 1992735 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1992735 times.
1992735 if (check_access(thd, SELECT_ACL, schema_name_ptr->ptr(), &db_access, nullptr,
8858 false, true))
8859 return false;
8860
8861
1/2
✓ Branch 0 taken 1992735 times.
✗ Branch 1 not taken.
1992735 TABLE_LIST table_list;
8862 1992735 table_list.db = schema_name_ptr->ptr();
8863 1992735 table_list.db_length = schema_name_ptr->length();
8864 1992735 table_list.table_name = table_name_ptr->ptr();
8865 1992735 table_list.table_name_length = table_name_ptr->length();
8866 1992735 table_list.grant.privilege = db_access;
8867
8868
2/2
✓ Branch 0 taken 1942182 times.
✓ Branch 1 taken 50553 times.
1992735 if (check_trigger_acl == false) {
8869
2/2
✓ Branch 0 taken 1940505 times.
✓ Branch 1 taken 1677 times.
1942182 if (db_access & TABLE_OP_ACLS) return true;
8870
8871 // Check table access
8872
3/4
✓ Branch 0 taken 1677 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1584 times.
✓ Branch 3 taken 93 times.
1677 if (check_grant(thd, TABLE_OP_ACLS, &table_list, true, 1, true))
8873 1584 return false;
8874 } else // Trigger check.
8875 {
8876 // Check trigger access
8877
3/4
✓ Branch 0 taken 50553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 50529 times.
101106 if (check_trigger_acl &&
8878
3/4
✓ Branch 0 taken 50553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 50529 times.
50553 check_table_access(thd, TRIGGER_ACL, &table_list, false, 1, true))
8879 24 return false;
8880 }
8881
8882 50622 return true;
8883 2073794 }
8884
8885 /**
8886 @brief
8887 INFORMATION_SCHEMA picks metadata from new DD using system views.
8888 In order for INFORMATION_SCHEMA to skip listing table for which
8889 the user does not have rights, the following UDF's is used.
8890
8891 Syntax:
8892 int CAN_ACCCESS_TABLE(schema_name, table_name);
8893
8894 @returns,
8895 1 - If current user has access.
8896 0 - If not.
8897 */
8898 2023240 longlong Item_func_can_access_table::val_int() {
8899
1/2
✓ Branch 0 taken 2023240 times.
✗ Branch 1 not taken.
2023240 DBUG_TRACE;
8900
8901
3/4
✓ Branch 0 taken 2023240 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1971015 times.
✓ Branch 3 taken 52225 times.
2023240 if (check_table_and_trigger_access(args, false, &null_value)) return 1;
8902
8903 52225 return 0;
8904 2023240 }
8905
8906 /**
8907 @brief
8908 INFORMATION_SCHEMA picks metadata from new DD using system views.
8909 In order for INFORMATION_SCHEMA to skip listing user accpounts for which
8910 the user does not have rights, the following SQL function is used.
8911
8912 Syntax:
8913 int CAN_ACCCESS_USER(user_part, host_part);
8914
8915 @returns,
8916 1 - If current user has access.
8917 0 - If not.
8918
8919 @sa @ref acl_can_access_user
8920 */
8921 173 longlong Item_func_can_access_user::val_int() {
8922
1/2
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
173 DBUG_TRACE;
8923
8924
1/2
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
173 THD *thd = current_thd;
8925 // Read user, host
8926 173 String user_name;
8927
1/2
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
173 String *user_name_ptr = args[0]->val_str(&user_name);
8928 173 String host_name;
8929
1/2
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
173 String *host_name_ptr = args[1]->val_str(&host_name);
8930
3/4
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 172 times.
173 if (host_name_ptr == nullptr || user_name_ptr == nullptr) {
8931 1 null_value = true;
8932 1 return 0;
8933 }
8934
8935 // Make sure we have safe string to access.
8936
1/2
✓ Branch 0 taken 172 times.
✗ Branch 1 not taken.
172 host_name_ptr->c_ptr_safe();
8937
1/2
✓ Branch 0 taken 172 times.
✗ Branch 1 not taken.
172 user_name_ptr->c_ptr_safe();
8938 172 MYSQL_LEX_STRING user_str = {const_cast<char *>(user_name_ptr->ptr()),
8939 172 user_name_ptr->length()};
8940 MYSQL_LEX_STRING
8941 172 host_str = {const_cast<char *>(host_name_ptr->ptr()),
8942 172 host_name_ptr->length()};
8943
1/2
✓ Branch 0 taken 172 times.
✗ Branch 1 not taken.
172 LEX_USER user;
8944
2/4
✓ Branch 0 taken 172 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 172 times.
172 if (!LEX_USER::init(&user, thd, &user_str, &host_str)) return 0;
8945
8946
3/4
✓ Branch 0 taken 172 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 122 times.
172 return acl_can_access_user(thd, &user) ? 1 : 0;
8947 173 }
8948
8949 /**
8950 @brief
8951 INFORMATION_SCHEMA picks metadata from new DD using system views. In
8952 order for INFORMATION_SCHEMA to skip listing table for which the user
8953 does not have rights on triggers, the following UDF's is used.
8954
8955 Syntax:
8956 int CAN_ACCCESS_TRIGGER(schema_name, table_name);
8957
8958 @returns,
8959 1 - If current user has access.
8960 0 - If not.
8961 */
8962 50554 longlong Item_func_can_access_trigger::val_int() {
8963
1/2
✓ Branch 0 taken 50554 times.
✗ Branch 1 not taken.
50554 DBUG_TRACE;
8964
8965
3/4
✓ Branch 0 taken 50554 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50529 times.
✓ Branch 3 taken 25 times.
50554 if (check_table_and_trigger_access(args, true, &null_value)) return 1;
8966
8967 25 return 0;
8968 50554 }
8969
8970 /**
8971 @brief
8972 INFORMATION_SCHEMA picks metadata from DD using system views. In
8973 order for INFORMATION_SCHEMA to skip listing routine for which the user
8974 does not have rights, the following UDF's is used.
8975
8976 Syntax:
8977 int CAN_ACCESS_ROUTINE(schema_name, name, type, user, definer,
8978 check_full_access);
8979
8980 @returns,
8981 1 - If current user has access.
8982 0 - If not.
8983 */
8984 450406 longlong Item_func_can_access_routine::val_int() {
8985
1/2
✓ Branch 0 taken 450406 times.
✗ Branch 1 not taken.
450406 DBUG_TRACE;
8986
8987 // Read schema_name, table_name
8988 450406 String schema_name;
8989 450406 String routine_name;
8990 450406 String type;
8991 450406 String definer;
8992
1/2
✓ Branch 0 taken 450406 times.
✗ Branch 1 not taken.
450406 String *schema_name_ptr = args[0]->val_str(&schema_name);
8993
1/2
✓ Branch 0 taken 450406 times.
✗ Branch 1 not taken.
450406 String *routine_name_ptr = args[1]->val_str(&routine_name);
8994
1/2
✓ Branch 0 taken 450406 times.
✗ Branch 1 not taken.
450406 String *type_ptr = args[2]->val_str(&type);
8995
1/2
✓ Branch 0 taken 450406 times.
✗ Branch 1 not taken.
450406 String *definer_ptr = args[3]->val_str(&definer);
8996
1/2
✓ Branch 0 taken 450406 times.
✗ Branch 1 not taken.
450406 bool check_full_access = args[4]->val_int();
8997
4/6
✓ Branch 0 taken 450405 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 450405 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 450405 times.
✗ Branch 5 not taken.
450406 if (schema_name_ptr == nullptr || routine_name_ptr == nullptr ||
8998
2/4
✓ Branch 0 taken 450405 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 450405 times.
450405 type_ptr == nullptr || definer_ptr == nullptr || args[4]->null_value) {
8999 1 null_value = true;
9000 1 return 0;
9001 }
9002
9003 // Make strings safe.
9004
1/2
✓ Branch 0 taken 450405 times.
✗ Branch 1 not taken.
450405 schema_name_ptr->c_ptr_safe();
9005
1/2
✓ Branch 0 taken 450405 times.
✗ Branch 1 not taken.
450405 routine_name_ptr->c_ptr_safe();
9006
1/2
✓ Branch 0 taken 450405 times.
✗ Branch 1 not taken.
450405 type_ptr->c_ptr_safe();
9007
1/2
✓ Branch 0 taken 450405 times.
✗ Branch 1 not taken.
450405 definer_ptr->c_ptr_safe();
9008
9009 450405 bool is_procedure = (strcmp(type_ptr->ptr(), "PROCEDURE") == 0);
9010
9011 // Skip INFORMATION_SCHEMA database
9012
4/6
✓ Branch 0 taken 450405 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 450405 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1665 times.
✓ Branch 5 taken 448740 times.
900810 if (is_infoschema_db(schema_name_ptr->ptr()) ||
9013
3/4
✓ Branch 0 taken 450405 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1665 times.
✓ Branch 3 taken 448740 times.
450405 !my_strcasecmp(system_charset_info, schema_name_ptr->ptr(), "sys"))
9014 1665 return 1;
9015
9016 /*
9017 Check if user has full access to the routine properties (i.e including
9018 stored routine code), or partial access (i.e to view its other properties).
9019 */
9020
9021 char user_name_holder[USERNAME_LENGTH + 1];
9022 448740 LEX_STRING user_name = {user_name_holder, USERNAME_LENGTH};
9023
9024 char host_name_holder[HOSTNAME_LENGTH + 1];
9025 448740 LEX_STRING host_name = {host_name_holder, HOSTNAME_LENGTH};
9026
9027
1/2
✓ Branch 0 taken 448740 times.
✗ Branch 1 not taken.
448740 parse_user(definer_ptr->ptr(), definer_ptr->length(), user_name.str,
9028 &user_name.length, host_name.str, &host_name.length);
9029
9030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 448740 times.
448740 if (lower_case_table_names == 2) {
9031 /*
9032 ACL code assumes that in l-c-t-n > 0 modes schema name passed to it
9033 is in lower case.
9034 */
9035 my_casedn_str(files_charset_info, schema_name_ptr->ptr());
9036 }
9037
9038
1/2
✓ Branch 0 taken 448740 times.
✗ Branch 1 not taken.
448740 THD *thd = current_thd;
9039
1/2
✓ Branch 0 taken 448740 times.
✗ Branch 1 not taken.
448740 bool full_access = has_full_view_routine_access(thd, schema_name_ptr->ptr(),
9040 448740 user_name.str, host_name.str);
9041
9042
2/2
✓ Branch 0 taken 223790 times.
✓ Branch 1 taken 224950 times.
448740 if (check_full_access) {
9043
2/2
✓ Branch 0 taken 223763 times.
✓ Branch 1 taken 27 times.
223790 return full_access ? 1 : 0;
9044
7/8
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 224848 times.
✓ Branch 2 taken 102 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 51 times.
✓ Branch 5 taken 51 times.
✓ Branch 6 taken 51 times.
✓ Branch 7 taken 224899 times.
225052 } else if (!full_access && !has_partial_view_routine_access(
9045 102 thd, schema_name_ptr->ptr(),
9046 102 routine_name_ptr->ptr(), is_procedure)) {
9047 51 return 0;
9048 }
9049
9050 224899 return 1;
9051 450406 }
9052
9053 /**
9054 @brief
9055 INFORMATION_SCHEMA picks metadata from DD using system views.
9056 In order for INFORMATION_SCHEMA to skip listing event for which
9057 the user does not have rights, the following internal functions are used.
9058
9059 Syntax:
9060 int CAN_ACCCESS_EVENT(schema_name);
9061
9062 @returns,
9063 1 - If current user has access.
9064 0 - If not.
9065 */
9066
9067 1128 longlong Item_func_can_access_event::val_int() {
9068
1/2
✓ Branch 0 taken 1128 times.
✗ Branch 1 not taken.
1128 DBUG_TRACE;
9069
9070 // Read schema_name
9071 1128 String schema_name;
9072
1/2
✓ Branch 0 taken 1128 times.
✗ Branch 1 not taken.
1128 String *schema_name_ptr = args[0]->val_str(&schema_name);
9073
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1127 times.
1128 if (schema_name_ptr == nullptr) {
9074 1 null_value = true;
9075 1 return 0;
9076 }
9077
9078 // Make sure we have safe string to access.
9079
1/2
✓ Branch 0 taken 1127 times.
✗ Branch 1 not taken.
1127 schema_name_ptr->c_ptr_safe();
9080
9081 // Check if schema is hidden.
9082
1/2
✓ Branch 0 taken 1127 times.
✗ Branch 1 not taken.
1127 THD *thd = current_thd;
9083
2/4
✓ Branch 0 taken 1127 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1127 times.
1127 if (is_hidden_by_ndb(thd, schema_name_ptr, nullptr)) return 0;
9084
9085 // Skip INFORMATION_SCHEMA database
9086
3/4
✓ Branch 0 taken 1127 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1125 times.
1127 if (is_infoschema_db(schema_name_ptr->ptr())) return 1;
9087
9088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1125 times.
1125 if (lower_case_table_names == 2) {
9089 /*
9090 ACL code assumes that in l-c-t-n > 0 modes schema name passed to it
9091 is in lower case.
9092 */
9093 my_casedn_str(files_charset_info, schema_name_ptr->ptr());
9094 }
9095
9096 // Check access
9097
3/4
✓ Branch 0 taken 1125 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1122 times.
1125 if (check_access(thd, EVENT_ACL, schema_name_ptr->ptr(), nullptr, nullptr,
9098 false, true)) {
9099 3 return 0;
9100 }
9101
9102 1122 return 1;
9103 1128 }
9104
9105 /**
9106 @brief
9107 INFORMATION_SCHEMA picks metadata from DD using system views.
9108 In order for INFORMATION_SCHEMA to skip listing resource groups for which
9109 the user does not have rights, the following internal functions are used.
9110
9111 Syntax:
9112 int CAN_ACCCESS_RESOURCE_GROUP(resource_group_name);
9113
9114 @returns,
9115 1 - If current user has access.
9116 0 - If not.
9117 */
9118
9119 26 longlong Item_func_can_access_resource_group::val_int() {
9120
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 DBUG_TRACE;
9121
9122
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 auto mgr_ptr = resourcegroups::Resource_group_mgr::instance();
9123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!mgr_ptr->resource_group_support()) {
9124 null_value = true;
9125 return false;
9126 }
9127
9128 // Read resource group name.
9129 26 String res_grp_name;
9130
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 String *res_grp_name_ptr = args[0]->val_str(&res_grp_name);
9131
9132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (res_grp_name_ptr == nullptr) {
9133 null_value = true;
9134 return false;
9135 }
9136
9137 // Make sure we have safe string to access.
9138
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 res_grp_name_ptr->c_ptr_safe();
9139
9140 26 MDL_ticket *ticket = nullptr;
9141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (mgr_ptr->acquire_shared_mdl_for_resource_group(
9142
3/6
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
26 current_thd, res_grp_name_ptr->c_ptr(), MDL_EXPLICIT, &ticket, false))
9143 return false;
9144
9145
3/6
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
26 auto res_grp_ptr = mgr_ptr->get_resource_group(res_grp_name_ptr->c_ptr());
9146 26 longlong result = true;
9147
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (res_grp_ptr != nullptr) {
9148
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 Security_context *sctx = current_thd->security_context();
9149
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 16 times.
26 if (res_grp_ptr->type() == resourcegroups::Type::SYSTEM_RESOURCE_GROUP) {
9150
8/16
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 6 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
16 if (!(sctx->check_access(SUPER_ACL) ||
9151
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 sctx->has_global_grant(STRING_WITH_LEN("RESOURCE_GROUP_ADMIN"))
9152
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 .first))
9153 4 result = false;
9154 } else {
9155
8/16
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 15 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
19 if (!(sctx->check_access(SUPER_ACL) ||
9156
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 sctx->has_global_grant(STRING_WITH_LEN("RESOURCE_GROUP_ADMIN"))
9157
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 .first ||
9158
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 sctx->has_global_grant(STRING_WITH_LEN("RESOURCE_GROUP_USER"))
9159
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 .first))
9160 1 result = false;
9161 }
9162 }
9163
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 mgr_ptr->release_shared_mdl_for_resource_group(current_thd, ticket);
9164
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 return res_grp_ptr != nullptr ? result : false;
9165 26 }
9166
9167 /**
9168 @brief
9169 INFORMATION_SCHEMA picks metadata from DD using system views.
9170 In order for INFORMATION_SCHEMA to skip listing column for which
9171 the user does not have rights, the following UDF's is used.
9172
9173 Syntax:
9174 int CAN_ACCCESS_COLUMN(schema_name,
9175 table_name,
9176 field_name);
9177
9178 @returns,
9179 1 - If current user has access.
9180 0 - If not.
9181 */
9182 19974077 longlong Item_func_can_access_column::val_int() {
9183
1/2
✓ Branch 0 taken 19974078 times.
✗ Branch 1 not taken.
19974077 DBUG_TRACE;
9184
9185 // Read schema_name, table_name
9186 19974078 String schema_name;
9187
1/2
✓ Branch 0 taken 19974078 times.
✗ Branch 1 not taken.
19974078 String *schema_name_ptr = args[0]->val_str(&schema_name);
9188 19974078 String table_name;
9189
1/2
✓ Branch 0 taken 19974078 times.
✗ Branch 1 not taken.
19974078 String *table_name_ptr = args[1]->val_str(&table_name);
9190
3/4
✓ Branch 0 taken 19974077 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19974077 times.
19974078 if (schema_name_ptr == nullptr || table_name_ptr == nullptr) {
9191 1 null_value = true;
9192 1 return 0;
9193 }
9194
9195 // Make sure we have safe string to access.
9196
1/2
✓ Branch 0 taken 19974077 times.
✗ Branch 1 not taken.
19974077 schema_name_ptr->c_ptr_safe();
9197
1/2
✓ Branch 0 taken 19974077 times.
✗ Branch 1 not taken.
19974077 table_name_ptr->c_ptr_safe();
9198
9199 // Check if table is hidden.
9200
1/2
✓ Branch 0 taken 19974077 times.
✗ Branch 1 not taken.
19974077 THD *thd = current_thd;
9201
2/4
✓ Branch 0 taken 19974077 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19974077 times.
19974077 if (is_hidden_by_ndb(thd, schema_name_ptr, table_name_ptr)) return 0;
9202
9203 // Read column_name.
9204 19974077 String column_name;
9205
1/2
✓ Branch 0 taken 19974077 times.
✗ Branch 1 not taken.
19974077 String *column_name_ptr = args[2]->val_str(&column_name);
9206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19974077 times.
19974077 if (column_name_ptr == nullptr) {
9207 null_value = true;
9208 return 0;
9209 }
9210
9211 // Make sure we have safe string to access.
9212
1/2
✓ Branch 0 taken 19974077 times.
✗ Branch 1 not taken.
19974077 column_name_ptr->c_ptr_safe();
9213
9214 // Skip INFORMATION_SCHEMA database
9215
3/4
✓ Branch 0 taken 19974077 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20655 times.
✓ Branch 3 taken 19953422 times.
19974077 if (is_infoschema_db(schema_name_ptr->ptr())) return 1;
9216
9217 // Check access
9218
1/2
✓ Branch 0 taken 19953422 times.
✗ Branch 1 not taken.
19953422 GRANT_INFO grant_info;
9219
9220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19953422 times.
19953422 if (lower_case_table_names == 2) {
9221 /*
9222 ACL code assumes that in l-c-t-n > 0 modes schema and table names
9223 passed to it are in lower case.
9224 */
9225 my_casedn_str(files_charset_info, schema_name_ptr->ptr());
9226 my_casedn_str(files_charset_info, table_name_ptr->ptr());
9227 }
9228
9229
2/4
✓ Branch 0 taken 19953421 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19953421 times.
19953422 if (check_access(thd, SELECT_ACL, schema_name_ptr->ptr(),
9230 &grant_info.privilege, nullptr, false, true))
9231 return 0;
9232
9233 uint col_access =
9234
1/2
✓ Branch 0 taken 19953422 times.
✗ Branch 1 not taken.
19953422 get_column_grant(thd, &grant_info, schema_name_ptr->ptr(),
9235 19953421 table_name_ptr->ptr(), column_name_ptr->ptr()) &
9236 19953422 COL_ACLS;
9237
2/2
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 19953191 times.
19953422 if (!col_access) {
9238 231 return 0;
9239 }
9240
9241 19953191 return 1;
9242 19974078 }
9243
9244 /**
9245 @brief
9246 INFORMATION_SCHEMA picks metadata from DD using system views.
9247 In order for INFORMATION_SCHEMA to skip listing view definition
9248 for the user without rights, the following UDF's is used.
9249
9250 Syntax:
9251 int CAN_ACCESS_VIEW(schema_name, view_name, definer, options);
9252
9253 @returns,
9254 1 - If current user has access.
9255 0 - If not.
9256 */
9257 554 longlong Item_func_can_access_view::val_int() {
9258
1/2
✓ Branch 0 taken 554 times.
✗ Branch 1 not taken.
554 DBUG_TRACE;
9259
9260 // Read schema_name, table_name
9261 554 String schema_name;
9262 554 String table_name;
9263 554 String definer;
9264 554 String options;
9265
1/2
✓ Branch 0 taken 554 times.
✗ Branch 1 not taken.
554 String *schema_name_ptr = args[0]->val_str(&schema_name);
9266
1/2
✓ Branch 0 taken 554 times.
✗ Branch 1 not taken.
554 String *table_name_ptr = args[1]->val_str(&table_name);
9267
1/2
✓ Branch 0 taken 554 times.
✗ Branch 1 not taken.
554 String *definer_ptr = args[2]->val_str(&definer);
9268
1/2
✓ Branch 0 taken 554 times.
✗ Branch 1 not taken.
554 String *options_ptr = args[3]->val_str(&options);
9269
4/6
✓ Branch 0 taken 553 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 553 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 553 times.
✗ Branch 5 not taken.
554 if (schema_name_ptr == nullptr || table_name_ptr == nullptr ||
9270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 553 times.
553 definer_ptr == nullptr || options_ptr == nullptr) {
9271 1 null_value = true;
9272 1 return 0;
9273 }
9274
9275 // Make strings safe.
9276
1/2
✓ Branch 0 taken 553 times.
✗ Branch 1 not taken.
553 schema_name_ptr->c_ptr_safe();
9277
1/2
✓ Branch 0 taken 553 times.
✗ Branch 1 not taken.
553 table_name_ptr->c_ptr_safe();
9278
1/2
✓ Branch 0 taken 553 times.
✗ Branch 1 not taken.
553 definer_ptr->c_ptr_safe();
9279
1/2
✓ Branch 0 taken 553 times.
✗ Branch 1 not taken.
553 options_ptr->c_ptr_safe();
9280
9281 // Skip INFORMATION_SCHEMA database
9282
4/6
✓ Branch 0 taken 553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 553 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 314 times.
✓ Branch 5 taken 239 times.
1106 if (is_infoschema_db(schema_name_ptr->ptr()) ||
9283
3/4
✓ Branch 0 taken 553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 314 times.
✓ Branch 3 taken 239 times.
553 !my_strcasecmp(system_charset_info, schema_name_ptr->ptr(), "sys"))
9284 314 return 1;
9285
9286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 239 times.
239 if (lower_case_table_names == 2) {
9287 /*
9288 ACL code assumes that in l-c-t-n > 0 modes schema and table names
9289 passed to it are in lower case. Although for view names lowercasing
9290 is not strictly necessary until bug#20356 is fixed we still do it
9291 to be consistent with CAN_ACCESS_TABLE().
9292 */
9293 schema_name_ptr->length(
9294 my_casedn_str(files_charset_info, schema_name_ptr->ptr()));
9295 table_name_ptr->length(
9296 my_casedn_str(files_charset_info, table_name_ptr->ptr()));
9297 }
9298
9299 // Check if view is valid. If view is invalid then push invalid view
9300 // warning.
9301 239 bool is_view_valid = true;
9302 std::unique_ptr<dd::Properties> view_options(
9303
3/6
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 239 times.
✗ Branch 5 not taken.
239 dd::Properties::parse_properties(options_ptr->c_ptr_safe()));
9304
9305 // Warn if the property string is corrupt.
9306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 239 times.
239 if (!view_options.get()) {
9307 LogErr(WARNING_LEVEL, ER_WARN_PROPERTY_STRING_PARSE_FAILED,
9308 options_ptr->c_ptr_safe());
9309 assert(false);
9310 return 0;
9311 }
9312
9313
3/6
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 239 times.
239 if (view_options->get("view_valid", &is_view_valid)) return 0;
9314
9315 // Show warning/error if view is invalid.
9316
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 THD *thd = current_thd;
9317
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 const String db_str(schema_name_ptr->c_ptr_safe(), system_charset_info);
9318
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 const String name_str(table_name_ptr->c_ptr_safe(), system_charset_info);
9319
4/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 173 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 230 times.
305 if (!is_view_valid &&
9320
3/4
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 57 times.
66 !thd->lex->m_IS_table_stats.check_error_for_key(db_str, name_str)) {
9321 std::string err_message = push_view_warning_or_error(
9322
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 current_thd, schema_name_ptr->ptr(), table_name_ptr->ptr());
9323
9324 /*
9325 Cache the error message, so that we do not show the same error multiple
9326 times.
9327 */
9328
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 thd->lex->m_IS_table_stats.store_error_message(db_str, name_str, nullptr,
9329 err_message.c_str());
9330 9 }
9331
9332 //
9333 // Check if definer user/host has access.
9334 //
9335
9336 239 Security_context *sctx = thd->security_context();
9337
9338 // NOTE: this is a copy/paste from sp_head::set_definer().
9339
9340 char user_name_holder[USERNAME_LENGTH + 1];
9341 239 LEX_STRING user_name = {user_name_holder, USERNAME_LENGTH};
9342
9343 char host_name_holder[HOSTNAME_LENGTH + 1];
9344 239 LEX_STRING host_name = {host_name_holder, HOSTNAME_LENGTH};
9345
9346
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 parse_user(definer_ptr->ptr(), definer_ptr->length(), user_name.str,
9347 &user_name.length, host_name.str, &host_name.length);
9348
9349
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 std::string definer_user(user_name.str, user_name.length);
9350
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 std::string definer_host(host_name.str, host_name.length);
9351
9352
5/6
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 211 times.
✓ Branch 3 taken 28 times.
✓ Branch 4 taken 211 times.
✓ Branch 5 taken 28 times.
450 if (!strcmp(definer_user.c_str(), sctx->priv_user().str) &&
9353
3/6
✓ Branch 0 taken 211 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 211 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 211 times.
✗ Branch 5 not taken.
211 !my_strcasecmp(system_charset_info, definer_host.c_str(),
9354 sctx->priv_host().str))
9355 211 return 1;
9356
9357 //
9358 // Check for ACL's
9359 //
9360
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 TABLE_LIST table_list;
9361 28 table_list.db = schema_name_ptr->ptr();
9362 28 table_list.db_length = schema_name_ptr->length();
9363 28 table_list.table_name = table_name_ptr->ptr();
9364 28 table_list.table_name_length = table_name_ptr->length();
9365
9366
3/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 16 times.
28 if (!check_table_access(thd, (SHOW_VIEW_ACL | SELECT_ACL), &table_list, false,
9367 1, true))
9368 12 return 1;
9369
9370 16 return 0;
9371 554 }
9372
9373 /**
9374 Skip hidden tables, columns, indexes and index elements. Additionally,
9375 skip generated invisible primary key(GIPK) and key column when system
9376 variable show_gipk_in_create_table_and_information_schema is set to
9377 OFF.
9378 Do *not* skip hidden tables, columns, indexes and index elements,
9379 when SHOW EXTENDED command are run. GIPK and key column are skipped
9380 even for SHOW EXTENED command.
9381
9382 Syntax:
9383 longlong IS_VISIBLE_DD_OBJECT(type_of_hidden_table [, is_object_hidden
9384 [, object_options]])
9385
9386 @returns,
9387 1 - If dd object is visible
9388 0 - If not visible.
9389 */
9390 22087056 longlong Item_func_is_visible_dd_object::val_int() {
9391
1/2
✓ Branch 0 taken 22087056 times.
✗ Branch 1 not taken.
22087056 DBUG_TRACE;
9392
9393
2/4
✓ Branch 0 taken 22087056 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22087056 times.
✗ Branch 3 not taken.
22087056 assert(arg_count > 0 && arg_count <= 3);
9394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22087056 times.
22087056 assert(args[0]->null_value == false);
9395
9396
4/6
✓ Branch 0 taken 22087056 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20096515 times.
✓ Branch 3 taken 1990541 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20096515 times.
22087056 if (args[0]->null_value || (arg_count >= 2 && args[1]->null_value)) {
9397 null_value = true;
9398 return false;
9399 }
9400
9401 22087056 null_value = false;
9402
1/2
✓ Branch 0 taken 22087056 times.
✗ Branch 1 not taken.
22087056 THD *thd = current_thd;
9403
9404 auto table_type =
9405
1/2
✓ Branch 0 taken 22087056 times.
✗ Branch 1 not taken.
22087056 static_cast<dd::Abstract_table::enum_hidden_type>(args[0]->val_int());
9406
9407 22087056 bool show_table = (table_type == dd::Abstract_table::HT_VISIBLE);
9408
9409 // Make I_S.TABLES show the hidden system view 'show_statistics' for
9410 // testing purpose.
9411
3/4
✓ Branch 0 taken 22087056 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 22087010 times.
22087056 DBUG_EXECUTE_IF("fetch_system_view_definition", { return 1; });
9412
9413
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 22086952 times.
22087010 if (thd->lex->m_extended_show)
9414 58 show_table =
9415
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
58 show_table || (table_type == dd::Abstract_table::HT_HIDDEN_DDL);
9416
9417
6/6
✓ Branch 0 taken 20096515 times.
✓ Branch 1 taken 1990495 times.
✓ Branch 2 taken 9863048 times.
✓ Branch 3 taken 10233467 times.
✓ Branch 4 taken 1180497 times.
✓ Branch 5 taken 10673046 times.
22087010 if (arg_count == 1 || show_table == false) return (show_table ? 1 : 0);
9418
9419 // Skip generated invisible primary key and key columns.
9420
6/8
✓ Branch 0 taken 10233467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10233467 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8160774 times.
✓ Branch 5 taken 2072693 times.
✓ Branch 6 taken 185 times.
✓ Branch 7 taken 10233282 times.
18394241 if (arg_count == 3 && !args[2]->is_null() &&
9421
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 8160589 times.
8160774 !thd->variables.show_gipk_in_create_table_and_information_schema) {
9422 185 String options;
9423
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
185 String *options_ptr = args[2]->val_str(&options);
9424
9425
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
185 if (options_ptr != nullptr) {
9426 // Read options from properties
9427 std::unique_ptr<dd::Properties> p(
9428
3/6
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 185 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 185 times.
✗ Branch 5 not taken.
185 dd::Properties::parse_properties(options_ptr->c_ptr_safe()));
9429
9430
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
185 if (p.get()) {
9431
4/6
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 185 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
✓ Branch 5 taken 97 times.
185 if (p->exists("gipk")) {
9432 88 bool gipk_value = false;
9433
2/4
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
88 p->get("gipk", &gipk_value);
9434
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 if (gipk_value) return 0;
9435 }
9436 } else {
9437 // Warn if the property string is corrupt.
9438 LogErr(WARNING_LEVEL, ER_WARN_PROPERTY_STRING_PARSE_FAILED,
9439 options_ptr->c_ptr_safe());
9440 assert(false);
9441 }
9442
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 88 times.
185 }
9443 /*
9444 Even if object is not a GIPK column/key we still need to check if it is
9445 marked as hidden.
9446 */
9447
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 88 times.
185 }
9448
9449 bool show_non_table_objects;
9450
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 10233333 times.
10233379 if (thd->lex->m_extended_show)
9451 46 show_non_table_objects = true;
9452 else
9453
1/2
✓ Branch 0 taken 10233333 times.
✗ Branch 1 not taken.
10233333 show_non_table_objects = (args[1]->val_bool() == false);
9454
9455
2/2
✓ Branch 0 taken 8166203 times.
✓ Branch 1 taken 2067176 times.
10233379 return show_non_table_objects ? 1 : 0;
9456 22087056 }
9457
9458 /**
9459 Get table statistics from dd::info_schema::get_table_statistics.
9460
9461 @param args List of parameters in following order,
9462
9463 - Schema_name
9464 - Table_name
9465 - Engine_name
9466 - se_private_id
9467 - Hidden_table
9468 - Tablespace_se_private_data
9469 - Table_se_private_data (Used if stype is AUTO_INC)
9470 - Partition name (optional argument).
9471
9472 @param arg_count Number of arguments in 'args'
9473
9474 @param stype Type of statistics that is requested
9475
9476 @param[out] null_value Marked true indicating NULL, if there is no value.
9477
9478 @returns ulonglong representing the statistics requested.
9479 */
9480
9481 443446 static ulonglong get_table_statistics(
9482 Item **args, uint arg_count, dd::info_schema::enum_table_stats_type stype,
9483 bool *null_value) {
9484
1/2
✓ Branch 0 taken 443446 times.
✗ Branch 1 not taken.
443446 DBUG_TRACE;
9485 443446 *null_value = false;
9486
9487 // Reads arguments
9488 443446 String schema_name;
9489 443446 String table_name;
9490 443446 String engine_name;
9491 443446 String ts_se_private_data;
9492 443446 String tbl_se_private_data;
9493 443446 String partition_name;
9494 443446 String *partition_name_ptr = nullptr;
9495
1/2
✓ Branch 0 taken 443446 times.
✗ Branch 1 not taken.
443446 String *schema_name_ptr = args[0]->val_str(&schema_name);
9496
1/2
✓ Branch 0 taken 443446 times.
✗ Branch 1 not taken.
443446 String *table_name_ptr = args[1]->val_str(&table_name);
9497
1/2
✓ Branch 0 taken 443446 times.
✗ Branch 1 not taken.
443446 String *engine_name_ptr = args[2]->val_str(&engine_name);
9498
1/2
✓ Branch 0 taken 443446 times.
✗ Branch 1 not taken.
443446 bool skip_hidden_table = args[4]->val_int();
9499
1/2
✓ Branch 0 taken 443446 times.
✗ Branch 1 not taken.
443446 String *ts_se_private_data_ptr = args[5]->val_str(&ts_se_private_data);
9500
1/2
✓ Branch 0 taken 443446 times.
✗ Branch 1 not taken.
443446 ulonglong stat_data = args[6]->val_uint();
9501
1/2
✓ Branch 0 taken 443446 times.
✗ Branch 1 not taken.
443446 ulonglong cached_timestamp = args[7]->val_uint();
9502
9503 443446 String *tbl_se_private_data_ptr = nullptr;
9504
9505 /*
9506 The same native function used by I_S.TABLES is used by I_S.PARTITIONS.
9507 We invoke native function with partition name only with I_S.PARTITIONS
9508 as a last argument. So, we check for argument count below, before
9509 reading partition name.
9510 */
9511
2/2
✓ Branch 0 taken 55381 times.
✓ Branch 1 taken 388065 times.
443446 if (stype == dd::info_schema::enum_table_stats_type::AUTO_INCREMENT) {
9512
1/2
✓ Branch 0 taken 55381 times.
✗ Branch 1 not taken.
55381 tbl_se_private_data_ptr = args[8]->val_str(&tbl_se_private_data);
9513
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 55381 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
55381 if (arg_count == 10) partition_name_ptr = args[9]->val_str(&partition_name);
9514
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 387728 times.
388065 } else if (arg_count == 9)
9515
1/2
✓ Branch 0 taken 337 times.
✗ Branch 1 not taken.
337 partition_name_ptr = args[8]->val_str(&partition_name);
9516
9517
4/6
✓ Branch 0 taken 443438 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 443438 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 443438 times.
✗ Branch 5 not taken.
443446 if (schema_name_ptr == nullptr || table_name_ptr == nullptr ||
9518
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 443422 times.
443438 engine_name_ptr == nullptr || skip_hidden_table) {
9519 24 *null_value = true;
9520 24 return 0;
9521 }
9522
9523 // Make sure we have safe string to access.
9524
1/2
✓ Branch 0 taken 443422 times.
✗ Branch 1 not taken.
443422 schema_name_ptr->c_ptr_safe();
9525
1/2
✓ Branch 0 taken 443422 times.
✗ Branch 1 not taken.
443422 table_name_ptr->c_ptr_safe();
9526
1/2
✓ Branch 0 taken 443422 times.
✗ Branch 1 not taken.
443422 engine_name_ptr->c_ptr_safe();
9527
9528 // Do not read dynamic stats for I_S tables.
9529
3/4
✓ Branch 0 taken 443422 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147391 times.
✓ Branch 3 taken 296031 times.
443422 if (is_infoschema_db(schema_name_ptr->ptr())) return 0;
9530
9531 // Read the statistic value from cache.
9532
1/2
✓ Branch 0 taken 296031 times.
✗ Branch 1 not taken.
296031 THD *thd = current_thd;
9533
1/2
✓ Branch 0 taken 296031 times.
✗ Branch 1 not taken.
296031 dd::Object_id se_private_id = (dd::Object_id)args[3]->val_uint();
9534
7/8
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 294976 times.
✓ Branch 2 taken 66072 times.
✓ Branch 3 taken 229959 times.
✓ Branch 4 taken 323 times.
✓ Branch 5 taken 295708 times.
✓ Branch 6 taken 296031 times.
✗ Branch 7 not taken.
363481 ulonglong result = thd->lex->m_IS_table_stats.read_stat(
9535 thd, *schema_name_ptr, *table_name_ptr, *engine_name_ptr,
9536
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 (partition_name_ptr ? partition_name_ptr->c_ptr_safe() : nullptr),
9537 se_private_id,
9538
1/2
✓ Branch 0 taken 66072 times.
✗ Branch 1 not taken.
66072 (ts_se_private_data_ptr ? ts_se_private_data_ptr->c_ptr_safe() : nullptr),
9539
1/2
✓ Branch 0 taken 1055 times.
✗ Branch 1 not taken.
1055 (tbl_se_private_data_ptr ? tbl_se_private_data_ptr->c_ptr_safe()
9540 : nullptr),
9541 stat_data, cached_timestamp, stype);
9542
9543 296031 return result;
9544 443446 }
9545
9546 55753 longlong Item_func_internal_table_rows::val_int() {
9547
1/2
✓ Branch 0 taken 55753 times.
✗ Branch 1 not taken.
55753 DBUG_TRACE;
9548
9549
1/2
✓ Branch 0 taken 55753 times.
✗ Branch 1 not taken.
55753 ulonglong result = get_table_statistics(
9550 args, arg_count, dd::info_schema::enum_table_stats_type::TABLE_ROWS,
9551 &null_value);
9552
9553
4/4
✓ Branch 0 taken 55752 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 55750 times.
55753 if (null_value == false && result == (ulonglong)-1) null_value = true;
9554
9555 55753 return result;
9556 55753 }
9557
9558 55204 longlong Item_func_internal_avg_row_length::val_int() {
9559
1/2
✓ Branch 0 taken 55204 times.
✗ Branch 1 not taken.
55204 DBUG_TRACE;
9560
9561
1/2
✓ Branch 0 taken 55204 times.
✗ Branch 1 not taken.
55204 ulonglong result = get_table_statistics(
9562 args, arg_count,
9563 dd::info_schema::enum_table_stats_type::TABLE_AVG_ROW_LENGTH,
9564 &null_value);
9565 55204 return result;
9566 55204 }
9567
9568 55748 longlong Item_func_internal_data_length::val_int() {
9569
1/2
✓ Branch 0 taken 55748 times.
✗ Branch 1 not taken.
55748 DBUG_TRACE;
9570
9571
1/2
✓ Branch 0 taken 55748 times.
✗ Branch 1 not taken.
55748 ulonglong result = get_table_statistics(
9572 args, arg_count, dd::info_schema::enum_table_stats_type::DATA_LENGTH,
9573 &null_value);
9574 55748 return result;
9575 55748 }
9576
9577 55208 longlong Item_func_internal_max_data_length::val_int() {
9578
1/2
✓ Branch 0 taken 55208 times.
✗ Branch 1 not taken.
55208 DBUG_TRACE;
9579
9580
1/2
✓ Branch 0 taken 55208 times.
✗ Branch 1 not taken.
55208 ulonglong result = get_table_statistics(
9581 args, arg_count, dd::info_schema::enum_table_stats_type::MAX_DATA_LENGTH,
9582 &null_value);
9583 55208 return result;
9584 55208 }
9585
9586 55754 longlong Item_func_internal_index_length::val_int() {
9587
1/2
✓ Branch 0 taken 55754 times.
✗ Branch 1 not taken.
55754 DBUG_TRACE;
9588
9589
1/2
✓ Branch 0 taken 55754 times.
✗ Branch 1 not taken.
55754 ulonglong result = get_table_statistics(
9590 args, arg_count, dd::info_schema::enum_table_stats_type::INDEX_LENGTH,
9591 &null_value);
9592 55754 return result;
9593 55754 }
9594
9595 55201 longlong Item_func_internal_data_free::val_int() {
9596
1/2
✓ Branch 0 taken 55201 times.
✗ Branch 1 not taken.
55201 DBUG_TRACE;
9597
9598
1/2
✓ Branch 0 taken 55201 times.
✗ Branch 1 not taken.
55201 ulonglong result = get_table_statistics(
9599 args, arg_count, dd::info_schema::enum_table_stats_type::DATA_FREE,
9600 &null_value);
9601
9602
3/4
✓ Branch 0 taken 55200 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 55200 times.
55201 if (null_value == false && result == (ulonglong)-1) null_value = true;
9603
9604 55201 return result;
9605 55201 }
9606
9607 55381 longlong Item_func_internal_auto_increment::val_int() {
9608
1/2
✓ Branch 0 taken 55381 times.
✗ Branch 1 not taken.
55381 DBUG_TRACE;
9609
9610
1/2
✓ Branch 0 taken 55381 times.
✗ Branch 1 not taken.
55381 ulonglong result = get_table_statistics(
9611 args, arg_count, dd::info_schema::enum_table_stats_type::AUTO_INCREMENT,
9612 &null_value);
9613
9614
4/4
✓ Branch 0 taken 55364 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 53061 times.
✓ Branch 3 taken 2303 times.
55381 if (null_value == false && result < (ulonglong)1) null_value = true;
9615
9616 55381 return result;
9617 55381 }
9618
9619 55197 longlong Item_func_internal_checksum::val_int() {
9620
1/2
✓ Branch 0 taken 55197 times.
✗ Branch 1 not taken.
55197 DBUG_TRACE;
9621
9622
1/2
✓ Branch 0 taken 55197 times.
✗ Branch 1 not taken.
55197 ulonglong result = get_table_statistics(
9623 args, arg_count, dd::info_schema::enum_table_stats_type::CHECKSUM,
9624 &null_value);
9625
9626
4/4
✓ Branch 0 taken 55196 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 55193 times.
✓ Branch 3 taken 3 times.
55197 if (null_value == false && result == 0) null_value = true;
9627
9628 55197 return result;
9629 55197 }
9630
9631 /**
9632 @brief
9633 INFORMATION_SCHEMA picks metadata from DD using system views.
9634 INFORMATION_SCHEMA.STATISTICS.COMMENT is used to indicate if the indexes are
9635 disabled by ALTER TABLE ... DISABLE KEYS. This property of table is stored
9636 in mysql.tables.options as 'keys_disabled=0/1/'. This internal function
9637 returns value of option 'keys_disabled' for a given table.
9638
9639 Syntax:
9640 int INTERNAL_KEYS_DISABLED(table_options);
9641
9642 @returns,
9643 1 - If keys are disabled.
9644 0 - If not.
9645 */
9646 1172 longlong Item_func_internal_keys_disabled::val_int() {
9647
1/2
✓ Branch 0 taken 1172 times.
✗ Branch 1 not taken.
1172 DBUG_TRACE;
9648
9649 // Read options.
9650 1172 String options;
9651
1/2
✓ Branch 0 taken 1172 times.
✗ Branch 1 not taken.
1172 String *options_ptr = args[0]->val_str(&options);
9652
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1171 times.
1172 if (options_ptr == nullptr) return 0;
9653
9654 // Read table option from properties
9655 std::unique_ptr<dd::Properties> p(
9656
3/6
✓ Branch 0 taken 1171 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1171 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1171 times.
✗ Branch 5 not taken.
1171 dd::Properties::parse_properties(options_ptr->c_ptr_safe()));
9657
9658 // Warn if the property string is corrupt.
9659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1171 times.
1171 if (!p.get()) {
9660 LogErr(WARNING_LEVEL, ER_WARN_PROPERTY_STRING_PARSE_FAILED,
9661 options_ptr->c_ptr_safe());
9662 assert(false);
9663 return 0;
9664 }
9665
9666 // Read keys_disabled sub type.
9667 1171 uint keys_disabled = 0;
9668
2/4
✓ Branch 0 taken 1171 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1171 times.
✗ Branch 3 not taken.
1171 p->get("keys_disabled", &keys_disabled);
9669
9670 1171 return keys_disabled;
9671 1172 }
9672
9673 /**
9674 @brief
9675 INFORMATION_SCHEMA picks metadata from DD using system views.
9676 INFORMATION_SCHEMA.STATISTICS.CARDINALITY reads data from SE.
9677
9678 Syntax:
9679 int INTERNAL_INDEX_COLUMN_CARDINALITY(
9680 schema_name,
9681 table_name,
9682 index_name,
9683 column_name,
9684 index_ordinal_position,
9685 column_ordinal_position,
9686 engine,
9687 se_private_id,
9688 is_hidden,
9689 stat_cardinality,
9690 cached_timestamp);
9691
9692 @returns Cardinatily. Or sets null_value to true if cardinality is -1.
9693 */
9694 3452 longlong Item_func_internal_index_column_cardinality::val_int() {
9695
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 DBUG_TRACE;
9696 3452 null_value = false;
9697
9698 // Read arguments
9699 3452 String schema_name;
9700 3452 String table_name;
9701 3452 String index_name;
9702 3452 String column_name;
9703 3452 String engine_name;
9704
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 String *schema_name_ptr = args[0]->val_str(&schema_name);
9705
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 String *table_name_ptr = args[1]->val_str(&table_name);
9706
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 String *index_name_ptr = args[2]->val_str(&index_name);
9707
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 String *column_name_ptr = args[3]->val_str(&column_name);
9708
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 uint index_ordinal_position = args[4]->val_uint();
9709
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 uint column_ordinal_position = args[5]->val_uint();
9710
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 String *engine_name_ptr = args[6]->val_str(&engine_name);
9711
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 dd::Object_id se_private_id = (dd::Object_id)args[7]->val_uint();
9712
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 bool hidden_index = args[8]->val_int();
9713
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 ulonglong stat_cardinality = args[9]->val_uint();
9714
1/2
✓ Branch 0 taken 3452 times.
✗ Branch 1 not taken.
3452 ulonglong cached_timestamp = args[10]->val_uint();
9715
9716 // stat_cardinality and cached_timestamp from mysql.index_stats can be null
9717 // when stat is fetched for 1st time without executing ANALYZE command.
9718
4/6
✓ Branch 0 taken 3451 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3451 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3451 times.
✗ Branch 5 not taken.
3452 if (schema_name_ptr == nullptr || table_name_ptr == nullptr ||
9719
2/4
✓ Branch 0 taken 3451 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3451 times.
✗ Branch 3 not taken.
3451 index_name_ptr == nullptr || engine_name_ptr == nullptr ||
9720
1/2
✓ Branch 0 taken 3451 times.
✗ Branch 1 not taken.
3451 column_name_ptr == nullptr || args[4]->null_value ||
9721
4/6
✓ Branch 0 taken 3451 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3451 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 3446 times.
3451 args[5]->null_value || args[8]->null_value || hidden_index) {
9722 6 null_value = true;
9723 6 return 0;
9724 }
9725
9726 // Make sure we have safe string to access.
9727
1/2
✓ Branch 0 taken 3446 times.
✗ Branch 1 not taken.
3446 schema_name_ptr->c_ptr_safe();
9728
1/2
✓ Branch 0 taken 3446 times.
✗ Branch 1 not taken.
3446 table_name_ptr->c_ptr_safe();
9729
1/2
✓ Branch 0 taken 3446 times.
✗ Branch 1 not taken.
3446 index_name_ptr->c_ptr_safe();
9730
1/2
✓ Branch 0 taken 3446 times.
✗ Branch 1 not taken.
3446 column_name_ptr->c_ptr_safe();
9731
1/2
✓ Branch 0 taken 3446 times.
✗ Branch 1 not taken.
3446 engine_name_ptr->c_ptr_safe();
9732
9733 3446 ulonglong result = 0;
9734
1/2
✓ Branch 0 taken 3446 times.
✗ Branch 1 not taken.
3446 THD *thd = current_thd;
9735
1/2
✓ Branch 0 taken 3446 times.
✗ Branch 1 not taken.
3446 result = thd->lex->m_IS_table_stats.read_stat(
9736 thd, *schema_name_ptr, *table_name_ptr, *index_name_ptr, nullptr,
9737 *column_name_ptr, index_ordinal_position - 1, column_ordinal_position - 1,
9738 *engine_name_ptr, se_private_id, nullptr, nullptr, stat_cardinality,
9739 cached_timestamp,
9740 dd::info_schema::enum_table_stats_type::INDEX_COLUMN_CARDINALITY);
9741
9742
2/2
✓ Branch 0 taken 1491 times.
✓ Branch 1 taken 1955 times.
3446 if (result == (ulonglong)-1) null_value = true;
9743
9744 3446 return result;
9745 3452 }
9746
9747 /**
9748 Retrieve tablespace statistics from SE
9749
9750 @param thd The current thread.
9751
9752 @param args List of parameters in following order,
9753
9754 - Tablespace_name
9755 - Engine_name
9756 - Tablespace_se_private_data
9757
9758 @param[out] null_value Marked true indicating NULL, if there is no value.
9759 */
9760
9761 491297 void retrieve_tablespace_statistics(THD *thd, Item **args, bool *null_value) {
9762
1/2
✓ Branch 0 taken 491297 times.
✗ Branch 1 not taken.
491297 DBUG_TRACE;
9763 491297 *null_value = false;
9764
9765 // Reads arguments
9766 491297 String tablespace_name;
9767
1/2
✓ Branch 0 taken 491297 times.
✗ Branch 1 not taken.
491297 String *tablespace_name_ptr = args[0]->val_str(&tablespace_name);
9768 491297 String file_name;
9769
1/2
✓ Branch 0 taken 491297 times.
✗ Branch 1 not taken.
491297 String *file_name_ptr = args[1]->val_str(&file_name);
9770 491297 String engine_name;
9771
1/2
✓ Branch 0 taken 491297 times.
✗ Branch 1 not taken.
491297 String *engine_name_ptr = args[2]->val_str(&engine_name);
9772 491297 String ts_se_private_data;
9773
1/2
✓ Branch 0 taken 491297 times.
✗ Branch 1 not taken.
491297 String *ts_se_private_data_ptr = args[3]->val_str(&ts_se_private_data);
9774
9775
4/6
✓ Branch 0 taken 491287 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 491287 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 491287 times.
491297 if (tablespace_name_ptr == nullptr || file_name_ptr == nullptr ||
9776 engine_name_ptr == nullptr) {
9777 10 *null_value = true;
9778 10 return;
9779 }
9780
9781 // Make sure we have safe string to access.
9782
1/2
✓ Branch 0 taken 491287 times.
✗ Branch 1 not taken.
491287 tablespace_name_ptr->c_ptr_safe();
9783
1/2
✓ Branch 0 taken 491287 times.
✗ Branch 1 not taken.
491287 file_name_ptr->c_ptr_safe();
9784
1/2
✓ Branch 0 taken 491287 times.
✗ Branch 1 not taken.
491287 engine_name_ptr->c_ptr_safe();
9785
9786 // Read the statistic value from cache.
9787
4/6
✓ Branch 0 taken 491287 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 491287 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 332 times.
✓ Branch 5 taken 490955 times.
982574 if (thd->lex->m_IS_tablespace_stats.read_stat(
9788 thd, *tablespace_name_ptr, *file_name_ptr, *engine_name_ptr,
9789
1/2
✓ Branch 0 taken 491287 times.
✗ Branch 1 not taken.
491287 (ts_se_private_data_ptr ? ts_se_private_data_ptr->c_ptr_safe()
9790 : nullptr)))
9791 332 *null_value = true;
9792
10/10
✓ Branch 0 taken 491287 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 491287 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 491287 times.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 491287 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 491287 times.
✓ Branch 9 taken 10 times.
491337 }
9793
9794 14971 longlong Item_func_internal_tablespace_id::val_int() {
9795
1/2
✓ Branch 0 taken 14971 times.
✗ Branch 1 not taken.
14971 DBUG_TRACE;
9796 14971 ulonglong result = -1;
9797
9798
1/2
✓ Branch 0 taken 14971 times.
✗ Branch 1 not taken.
14971 THD *thd = current_thd;
9799
1/2
✓ Branch 0 taken 14971 times.
✗ Branch 1 not taken.
14971 retrieve_tablespace_statistics(thd, args, &null_value);
9800
2/2
✓ Branch 0 taken 14639 times.
✓ Branch 1 taken 332 times.
14971 if (null_value == false) {
9801
1/2
✓ Branch 0 taken 14639 times.
✗ Branch 1 not taken.
14639 thd->lex->m_IS_tablespace_stats.get_stat(
9802 dd::info_schema::enum_tablespace_stats_type::TS_ID, &result);
9803 14639 return result;
9804 }
9805
9806 332 return result;
9807 14971 }
9808
9809 2 longlong Item_func_internal_tablespace_logfile_group_number::val_int() {
9810
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 DBUG_TRACE;
9811 2 ulonglong result = -1;
9812
9813
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 THD *thd = current_thd;
9814
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 retrieve_tablespace_statistics(thd, args, &null_value);
9815
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (null_value == false) {
9816
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd->lex->m_IS_tablespace_stats.get_stat(
9817 dd::info_schema::enum_tablespace_stats_type::TS_LOGFILE_GROUP_NUMBER,
9818 &result);
9819
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (result == (ulonglong)-1) null_value = true;
9820
9821 2 return result;
9822 }
9823
9824 return result;
9825 2 }
9826
9827 11 longlong Item_func_internal_tablespace_free_extents::val_int() {
9828
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 DBUG_TRACE;
9829 11 ulonglong result = -1;
9830
9831
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 THD *thd = current_thd;
9832
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 retrieve_tablespace_statistics(thd, args, &null_value);
9833
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 if (null_value == false) {
9834
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 thd->lex->m_IS_tablespace_stats.get_stat(
9835 dd::info_schema::enum_tablespace_stats_type::TS_FREE_EXTENTS, &result);
9836 10 return result;
9837 }
9838
9839 1 return result;
9840 11 }
9841
9842 11 longlong Item_func_internal_tablespace_total_extents::val_int() {
9843
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 DBUG_TRACE;
9844 11 ulonglong result = -1;
9845
9846
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 THD *thd = current_thd;
9847
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 retrieve_tablespace_statistics(thd, args, &null_value);
9848
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 if (null_value == false) {
9849
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 thd->lex->m_IS_tablespace_stats.get_stat(
9850 dd::info_schema::enum_tablespace_stats_type::TS_TOTAL_EXTENTS, &result);
9851 10 return result;
9852 }
9853
9854 1 return result;
9855 11 }
9856
9857 11 longlong Item_func_internal_tablespace_extent_size::val_int() {
9858
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 DBUG_TRACE;
9859 11 ulonglong result = -1;
9860
9861
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 THD *thd = current_thd;
9862
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 retrieve_tablespace_statistics(thd, args, &null_value);
9863
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 if (null_value == false) {
9864
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 thd->lex->m_IS_tablespace_stats.get_stat(
9865 dd::info_schema::enum_tablespace_stats_type::TS_EXTENT_SIZE, &result);
9866 10 return result;
9867 }
9868
9869 1 return result;
9870 11 }
9871
9872 9 longlong Item_func_internal_tablespace_initial_size::val_int() {
9873
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 DBUG_TRACE;
9874 9 ulonglong result = -1;
9875
9876
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 THD *thd = current_thd;
9877
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 retrieve_tablespace_statistics(thd, args, &null_value);
9878
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 if (null_value == false) {
9879
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 thd->lex->m_IS_tablespace_stats.get_stat(
9880 dd::info_schema::enum_tablespace_stats_type::TS_INITIAL_SIZE, &result);
9881 8 return result;
9882 }
9883
9884 1 return result;
9885 9 }
9886
9887 11 longlong Item_func_internal_tablespace_maximum_size::val_int() {
9888
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 DBUG_TRACE;
9889 11 ulonglong result = -1;
9890
9891
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 THD *thd = current_thd;
9892
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 retrieve_tablespace_statistics(thd, args, &null_value);
9893
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 if (null_value == false) {
9894
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 thd->lex->m_IS_tablespace_stats.get_stat(
9895 dd::info_schema::enum_tablespace_stats_type::TS_MAXIMUM_SIZE, &result);
9896
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 if (result == (ulonglong)-1) null_value = true;
9897
9898 10 return result;
9899 }
9900
9901 1 return result;
9902 11 }
9903
9904 9 longlong Item_func_internal_tablespace_autoextend_size::val_int() {
9905
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 DBUG_TRACE;
9906 9 ulonglong result = -1;
9907
9908
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 THD *thd = current_thd;
9909
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 retrieve_tablespace_statistics(thd, args, &null_value);
9910
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 if (null_value == false) {
9911
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 thd->lex->m_IS_tablespace_stats.get_stat(
9912 dd::info_schema::enum_tablespace_stats_type::TS_AUTOEXTEND_SIZE,
9913 &result);
9914 8 return result;
9915 }
9916
9917 1 return result;
9918 9 }
9919
9920 2 longlong Item_func_internal_tablespace_version::val_int() {
9921
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 DBUG_TRACE;
9922 2 ulonglong result = -1;
9923
9924
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 THD *thd = current_thd;
9925
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 retrieve_tablespace_statistics(thd, args, &null_value);
9926
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (null_value == false) {
9927
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd->lex->m_IS_tablespace_stats.get_stat(
9928 dd::info_schema::enum_tablespace_stats_type::TS_VERSION, &result);
9929
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (result == (ulonglong)-1) null_value = true;
9930
9931 2 return result;
9932 }
9933
9934 return result;
9935 2 }
9936
9937 11 longlong Item_func_internal_tablespace_data_free::val_int() {
9938
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 DBUG_TRACE;
9939 11 ulonglong result = -1;
9940
9941
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 THD *thd = current_thd;
9942
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 retrieve_tablespace_statistics(thd, args, &null_value);
9943
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 if (null_value == false) {
9944
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 thd->lex->m_IS_tablespace_stats.get_stat(
9945 dd::info_schema::enum_tablespace_stats_type::TS_DATA_FREE, &result);
9946 10 return result;
9947 }
9948
9949 1 return result;
9950 11 }
9951
9952 6276 Item_func_version::Item_func_version(const POS &pos)
9953 12552 : Item_static_string_func(pos, NAME_STRING("version()"), server_version,
9954 strlen(server_version), system_charset_info,
9955
1/2
✓ Branch 0 taken 6276 times.
✗ Branch 1 not taken.
6276 DERIVATION_SYSCONST) {}
9956
9957 /*
9958 Syntax:
9959 string get_dd_char_length()
9960 */
9961 16067029 longlong Item_func_internal_dd_char_length::val_int() {
9962
1/2
✓ Branch 0 taken 16067029 times.
✗ Branch 1 not taken.
16067029 DBUG_TRACE;
9963 16067029 null_value = false;
9964
9965
1/2
✓ Branch 0 taken 16067029 times.
✗ Branch 1 not taken.
16067029 dd::enum_column_types col_type = (dd::enum_column_types)args[0]->val_int();
9966
1/2
✓ Branch 0 taken 16067029 times.
✗ Branch 1 not taken.
16067029 uint field_length = args[1]->val_int();
9967 16067029 String cs_name;
9968
1/2
✓ Branch 0 taken 16067029 times.
✗ Branch 1 not taken.
16067029 String *cs_name_ptr = args[2]->val_str(&cs_name);
9969
1/2
✓ Branch 0 taken 16067029 times.
✗ Branch 1 not taken.
16067029 uint flag = args[3]->val_int();
9970
9971 // Stop if we found a NULL argument.
9972
4/6
✓ Branch 0 taken 15619530 times.
✓ Branch 1 taken 447499 times.
✓ Branch 2 taken 15619530 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15619530 times.
✗ Branch 5 not taken.
16067029 if (args[0]->null_value || args[1]->null_value || cs_name_ptr == nullptr ||
9973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15619530 times.
15619530 args[3]->null_value) {
9974 447499 null_value = true;
9975 447499 return 0;
9976 }
9977
9978 // Read character set.
9979
2/4
✓ Branch 0 taken 15619530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15619530 times.
✗ Branch 3 not taken.
15619530 CHARSET_INFO *cs = get_charset_by_name(cs_name_ptr->c_ptr_safe(), MYF(0));
9980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15619530 times.
15619530 if (!cs) {
9981 null_value = true;
9982 return 0;
9983 }
9984
9985 // Check data types for getting info
9986
1/2
✓ Branch 0 taken 15619530 times.
✗ Branch 1 not taken.
15619530 enum_field_types field_type = dd_get_old_field_type(col_type);
9987 15619530 bool blob_flag = is_blob(field_type);
9988
6/6
✓ Branch 0 taken 13579214 times.
✓ Branch 1 taken 2040316 times.
✓ Branch 2 taken 10545216 times.
✓ Branch 3 taken 3033998 times.
✓ Branch 4 taken 10346064 times.
✓ Branch 5 taken 199152 times.
15619530 if (!blob_flag && field_type != MYSQL_TYPE_ENUM &&
9989
2/2
✓ Branch 0 taken 8936699 times.
✓ Branch 1 taken 1409365 times.
10346064 field_type != MYSQL_TYPE_SET &&
9990
2/2
✓ Branch 0 taken 5502739 times.
✓ Branch 1 taken 3433960 times.
8936699 field_type != MYSQL_TYPE_VARCHAR && // For varbinary type
9991 field_type != MYSQL_TYPE_STRING) // For binary type
9992 {
9993 5502739 null_value = true;
9994 5502739 return 0;
9995 }
9996
9997
2/4
✓ Branch 0 taken 10116791 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10116791 times.
✗ Branch 3 not taken.
20233582 std::ostringstream oss("");
9998
5/6
✓ Branch 0 taken 1790324 times.
✓ Branch 1 taken 140 times.
✓ Branch 2 taken 199076 times.
✓ Branch 3 taken 50776 times.
✓ Branch 4 taken 8076475 times.
✗ Branch 5 not taken.
10116791 switch (field_type) {
9999 1790324 case MYSQL_TYPE_BLOB:
10000 1790324 field_length = 65535;
10001 1790324 break;
10002 140 case MYSQL_TYPE_TINY_BLOB:
10003 140 field_length = 255;
10004 140 break;
10005 199076 case MYSQL_TYPE_MEDIUM_BLOB:
10006 199076 field_length = 16777215;
10007 199076 break;
10008 50776 case MYSQL_TYPE_LONG_BLOB:
10009 50776 field_length = 4294967295;
10010 50776 break;
10011 8076475 case MYSQL_TYPE_ENUM:
10012 case MYSQL_TYPE_SET:
10013 case MYSQL_TYPE_VAR_STRING:
10014 case MYSQL_TYPE_VARCHAR:
10015 case MYSQL_TYPE_STRING:
10016 8076475 break;
10017 default:
10018 break;
10019 }
10020
10021
4/4
✓ Branch 0 taken 5058402 times.
✓ Branch 1 taken 5058389 times.
✓ Branch 2 taken 5057958 times.
✓ Branch 3 taken 444 times.
10116791 if (!flag && field_length) {
10022
2/2
✓ Branch 0 taken 1020158 times.
✓ Branch 1 taken 4037800 times.
5057958 if (blob_flag)
10023 1020158 return field_length / cs->mbminlen;
10024 else
10025 4037800 return field_length / cs->mbmaxlen;
10026
4/4
✓ Branch 0 taken 5058389 times.
✓ Branch 1 taken 444 times.
✓ Branch 2 taken 5057945 times.
✓ Branch 3 taken 444 times.
5058833 } else if (flag && field_length) {
10027 5057945 return field_length;
10028 }
10029
10030 888 return 0;
10031 16067029 }
10032
10033 1956501 longlong Item_func_internal_get_view_warning_or_error::val_int() {
10034
1/2
✓ Branch 0 taken 1956501 times.
✗ Branch 1 not taken.
1956501 DBUG_TRACE;
10035
10036 1956501 String schema_name;
10037 1956501 String table_name;
10038 1956501 String table_type;
10039
1/2
✓ Branch 0 taken 1956501 times.
✗ Branch 1 not taken.
1956501 String *schema_name_ptr = args[0]->val_str(&schema_name);
10040
1/2
✓ Branch 0 taken 1956501 times.
✗ Branch 1 not taken.
1956501 String *table_name_ptr = args[1]->val_str(&table_name);
10041
1/2
✓ Branch 0 taken 1956501 times.
✗ Branch 1 not taken.
1956501 String *table_type_ptr = args[2]->val_str(&table_type);
10042
10043
4/6
✓ Branch 0 taken 1956500 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1956500 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1956500 times.
1956501 if (table_type_ptr == nullptr || schema_name_ptr == nullptr ||
10044 table_name_ptr == nullptr) {
10045 1 return 0;
10046 }
10047
10048 1956500 String options;
10049
1/2
✓ Branch 0 taken 1956500 times.
✗ Branch 1 not taken.
1956500 String *options_ptr = args[3]->val_str(&options);
10050
6/8
✓ Branch 0 taken 1956500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16006 times.
✓ Branch 3 taken 1940494 times.
✓ Branch 4 taken 16006 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16006 times.
✓ Branch 7 taken 1940494 times.
1956500 if (strcmp(table_type_ptr->c_ptr_safe(), "VIEW") == 0 &&
10051 options_ptr != nullptr) {
10052 16006 bool is_view_valid = true;
10053 std::unique_ptr<dd::Properties> view_options(
10054
3/6
✓ Branch 0 taken 16006 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16006 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16006 times.
✗ Branch 5 not taken.
16006 dd::Properties::parse_properties(options_ptr->c_ptr_safe()));
10055
10056 // Warn if the property string is corrupt.
10057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16006 times.
16006 if (!view_options.get()) {
10058 LogErr(WARNING_LEVEL, ER_WARN_PROPERTY_STRING_PARSE_FAILED,
10059 options_ptr->c_ptr_safe());
10060 assert(false);
10061 return 0;
10062 }
10063
10064 // Return 0 if get_bool() or push_view_warning_or_error() fails
10065
3/6
✓ Branch 0 taken 16006 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16006 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16006 times.
16006 if (view_options->get("view_valid", &is_view_valid)) return 0;
10066
10067
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15991 times.
16006 if (is_view_valid == false) {
10068
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 push_view_warning_or_error(current_thd, schema_name_ptr->c_ptr_safe(),
10069
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 table_name_ptr->c_ptr_safe());
10070 15 return 0;
10071 }
10072
2/2
✓ Branch 0 taken 15991 times.
✓ Branch 1 taken 15 times.
16006 }
10073
10074 1956485 return 1;
10075 1956501 }
10076
10077 /**
10078 @brief
10079 INFORMATION_SCHEMA picks metadata from DD using system views.
10080 INFORMATION_SCHEMA.STATISTICS.SUB_PART represents index sub part length.
10081 This internal function is used to get index sub part length.
10082
10083 Syntax:
10084 int GET_DD_INDEX_SUB_PART_LENGTH(
10085 index_column_usage_length,
10086 column_type,
10087 column_length,
10088 column_collation_id,
10089 index_type);
10090
10091 @returns Index sub part length.
10092 */
10093 3243 longlong Item_func_get_dd_index_sub_part_length::val_int() {
10094
1/2
✓ Branch 0 taken 3243 times.
✗ Branch 1 not taken.
3243 DBUG_TRACE;
10095 3243 null_value = true;
10096
10097 // Read arguments
10098
1/2
✓ Branch 0 taken 3243 times.
✗ Branch 1 not taken.
3243 uint key_part_length = args[0]->val_int();
10099 dd::enum_column_types col_type =
10100
1/2
✓ Branch 0 taken 3243 times.
✗ Branch 1 not taken.
3243 static_cast<dd::enum_column_types>(args[1]->val_int());
10101
1/2
✓ Branch 0 taken 3243 times.
✗ Branch 1 not taken.
3243 uint column_length = args[2]->val_int();
10102
1/2
✓ Branch 0 taken 3243 times.
✗ Branch 1 not taken.
3243 uint csid = args[3]->val_int();
10103 dd::Index::enum_index_type idx_type =
10104
1/2
✓ Branch 0 taken 3243 times.
✗ Branch 1 not taken.
3243 static_cast<dd::Index::enum_index_type>(args[4]->val_int());
10105
4/6
✓ Branch 0 taken 3237 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3237 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3237 times.
✗ Branch 5 not taken.
3243 if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
10106
2/4
✓ Branch 0 taken 3237 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3237 times.
3237 args[3]->null_value || args[4]->null_value)
10107 6 return 0;
10108
10109 // Read server col_type and check if we have key part.
10110
1/2
✓ Branch 0 taken 3237 times.
✗ Branch 1 not taken.
3237 enum_field_types field_type = dd_get_old_field_type(col_type);
10111
3/4
✓ Branch 0 taken 3237 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1722 times.
✓ Branch 3 taken 1515 times.
3237 if (!Field::type_can_have_key_part(field_type)) return 0;
10112
10113 // Calculate the key length for the column. Note that we pass inn dummy values
10114 // for "decimals", "is_unsigned" and "elements" since none of those arguments
10115 // will affect the key length for any of the data types that can have a prefix
10116 // index (see Field::type_can_have_key_part above).
10117 uint32 column_key_length =
10118
1/2
✓ Branch 0 taken 1515 times.
✗ Branch 1 not taken.
1515 calc_key_length(field_type, column_length, 0, false, 0);
10119
10120 // Read column charset id from args[3]
10121 1515 const CHARSET_INFO *column_charset = &my_charset_latin1;
10122
1/2
✓ Branch 0 taken 1515 times.
✗ Branch 1 not taken.
1515 if (csid) {
10123
1/2
✓ Branch 0 taken 1515 times.
✗ Branch 1 not taken.
1515 column_charset = get_charset(csid, MYF(0));
10124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1515 times.
1515 assert(column_charset);
10125 }
10126
10127
4/4
✓ Branch 0 taken 1483 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 190 times.
✓ Branch 3 taken 1293 times.
1515 if ((idx_type != dd::Index::IT_FULLTEXT) &&
10128 (key_part_length != column_key_length)) {
10129 190 longlong sub_part_length = key_part_length / column_charset->mbmaxlen;
10130 190 null_value = false;
10131 190 return sub_part_length;
10132 }
10133
10134 1325 return 0;
10135 3243 }
10136
10137 /**
10138 @brief
10139 Internal function used by INFORMATION_SCHEMA implementation to check
10140 if a role is a mandatory role.
10141
10142 Syntax:
10143 int INTERNAL_IS_MANDATORY_ROLE(role_user, role_host);
10144
10145 @returns,
10146 1 - If the role is mandatory.
10147 0 - If not.
10148 */
10149
10150 156 longlong Item_func_internal_is_mandatory_role::val_int() {
10151
1/2
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
156 DBUG_TRACE;
10152
10153 // Read schema_name
10154 156 String role_name;
10155
1/2
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
156 String *role_name_ptr = args[0]->val_str(&role_name);
10156 156 String role_host;
10157
1/2
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
156 String *role_host_ptr = args[1]->val_str(&role_host);
10158
3/4
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 155 times.
156 if (role_name_ptr == nullptr || role_host_ptr == nullptr) {
10159 1 null_value = true;
10160 1 return 0;
10161 }
10162
10163 // Create Auth_id for ID being searched.
10164 LEX_CSTRING lex_user;
10165
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 lex_user.str = role_name_ptr->c_ptr_safe();
10166 155 lex_user.length = role_name_ptr->length();
10167
10168 LEX_CSTRING lex_host;
10169
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 lex_host.str = role_host_ptr->c_ptr_safe();
10170 155 lex_host.length = role_host_ptr->length();
10171
10172 155 bool is_mandatory{false};
10173
3/4
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 154 times.
155 if (is_mandatory_role(lex_user, lex_host, &is_mandatory)) {
10174 4 push_warning_printf(
10175
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 current_thd, Sql_condition::SL_WARNING,
10176 ER_FAILED_TO_DETERMINE_IF_ROLE_IS_MANDATORY,
10177
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ER_THD(current_thd, ER_FAILED_TO_DETERMINE_IF_ROLE_IS_MANDATORY),
10178 lex_user.str, lex_host.str);
10179 }
10180
10181 155 return is_mandatory;
10182 156 }
10183
10184 /**
10185 @brief
10186 Internal function used by INFORMATION_SCHEMA implementation to check
10187 if a role enabled.
10188
10189 Syntax:
10190 int INTERNAL_IS_ENABLED_ROLE(role_user, role_host);
10191
10192 @returns,
10193 1 - If the role is enabled.
10194 0 - If not.
10195 */
10196
10197 436 longlong Item_func_internal_is_enabled_role::val_int() {
10198
1/2
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
436 DBUG_TRACE;
10199
1/2
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
436 THD *thd = current_thd;
10200
10201 // Read schema_name
10202 436 String role_name;
10203
1/2
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
436 String *role_name_ptr = args[0]->val_str(&role_name);
10204 436 String role_host;
10205
1/2
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
436 String *role_host_ptr = args[1]->val_str(&role_host);
10206
3/4
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 435 times.
436 if (role_name_ptr == nullptr || role_host_ptr == nullptr) {
10207 1 null_value = true;
10208 1 return 0;
10209 }
10210
10211
3/4
✓ Branch 0 taken 435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 199 times.
✓ Branch 3 taken 236 times.
435 if (thd->m_main_security_ctx.get_active_roles()->size() == 0) return 0;
10212
10213 // Create Auth_id for ID being searched.
10214 LEX_CSTRING lex_user;
10215
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
236 lex_user.str = role_name_ptr->c_ptr_safe();
10216 236 lex_user.length = role_name_ptr->length();
10217
10218 LEX_CSTRING lex_host;
10219
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
236 lex_host.str = role_host_ptr->c_ptr_safe();
10220 236 lex_host.length = role_host_ptr->length();
10221
10222 // Match the ID and return true if found.
10223
3/4
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✓ Branch 3 taken 185 times.
426 for (auto &rid : *thd->m_main_security_ctx.get_active_roles()) {
10224
4/6
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 51 times.
✓ Branch 5 taken 190 times.
241 if (rid == std::make_pair(lex_user, lex_host)) return 1;
10225 }
10226
10227 185 return 0;
10228 436 }
10229